-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.d.ts
60 lines (52 loc) · 2.04 KB
/
index.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
type NonNullSkipArray<T> = NonNullable<T> extends infer T1
? T1 extends unknown[]
? NonNullable<T1[number]>
: T1
: never;
type Tail<Path extends any[]> = ((...args: Path) => any) extends (_: any, ..._1: infer Rest) => any ? Rest : never;
type Id<T> = { [K in keyof T]: T[K] } & {};
declare const error: unique symbol;
declare const path: unique symbol;
declare const object: unique symbol;
/**
* interface describing a non-existing key passed as a Path argument to DeepExtractTypeSkipArrays or DeepExtractType
*/
export interface KeyNotFoundTypeError<O, K> {
[error]: "key not found";
[path]: K;
[object]: O;
}
type ___PickSkipArrays<T, Path extends [...string[]]> = Path extends [keyof T, ...any[]]
? {
[Head in Path[0]]: ___PickSkipArrays<NonNullSkipArray<T[Path[0]]>, Tail<Path>>;
}[Path[0]]
: Path extends [any, ...any[]]
? KeyNotFoundTypeError<T, Path[0]>
: T;
/**
* Extracts a deeply-nested type from the target `Path` in `Source`, skipping arrays and ignoring null|undefined|optional types:
* @example
* type QueryResult = { allPosts?: Array<{ users?: Array<{ name: string }> }> }
* // will be { name: string }
* type User = DeepExtractTypeSkipArrays<QueryResult, ["allPosts", "users"]>
*/
export type DeepExtractTypeSkipArrays<Source, Path extends [...string[]]> = Id<
NonNullSkipArray<___PickSkipArrays<NonNullable<Source>, Path>>
>;
type ___Pick<T, Path extends [...(string | number)[]]> = Path extends [keyof T, ...any[]]
? {
[Head in Path[0]]: ___Pick<NonNullable<T[Path[0]]>, Tail<Path>>;
}[Path[0]]
: Path extends [any, ...any[]]
? KeyNotFoundTypeError<T, Path[0]>
: T;
/**
* Extracts a deeply-nested type from the target `Path` in `Source`, ignoring null|undefined|optional types:
* @example
* type QueryResult = { user?: { firstPost?: { title: string } } };
* // will be { title: string }
* type Post = DeepExtractType<QueryResult, ["user", "firstPost"]>;
*/
export type DeepExtractType<Source, Path extends [...(string | number)[]]> = Id<
NonNullable<___Pick<NonNullable<Source>, Path>>
>;