forked from sindresorhus/type-fest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
get.ts
81 lines (66 loc) · 2.08 KB
/
get.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import {Get} from '../ts41/get';
import {expectTypeOf} from 'expect-type';
declare const get: <ObjectType, Path extends string>(object: ObjectType, path: Path) => Get<ObjectType, Path>;
interface ApiResponse {
hits: {
hits: Array<{
_id: string;
_source: {
name: Array<{
given: string[];
family: string;
}>;
birthDate: string;
};
}>;
};
}
declare const apiResponse: ApiResponse;
expectTypeOf(get(apiResponse, 'hits.hits[0]._source.name')).toEqualTypeOf<Array<{given: string[]; family: string}>>();
expectTypeOf(get(apiResponse, 'hits.hits.0._source.name')).toEqualTypeOf<Array<{given: string[]; family: string}>>();
expectTypeOf(get(apiResponse, 'hits.hits[0]._source.name[0].given[0]')).toBeString();
// TypeScript is structurally typed. It's *possible* this value exists even though it's not on the parent interface, so the type is `unknown`.
expectTypeOf(get(apiResponse, 'hits.someNonsense.notTheRightPath')).toBeUnknown();
// This interface uses a tuple type (as opposed to an array).
interface WithTuples {
foo: [
{
bar: number;
},
{
baz: boolean;
}
];
}
expectTypeOf<Get<WithTuples, 'foo[0].bar'>>().toBeNumber();
expectTypeOf<Get<WithTuples, 'foo.0.bar'>>().toBeNumber();
expectTypeOf<Get<WithTuples, 'foo[1].baz'>>().toBeBoolean();
expectTypeOf<Get<WithTuples, 'foo[1].bar'>>().toBeUnknown();
interface WithNumberKeys {
foo: {
1: {
bar: number;
};
};
}
expectTypeOf<Get<WithNumberKeys, 'foo[1].bar'>>().toBeNumber();
expectTypeOf<Get<WithNumberKeys, 'foo.1.bar'>>().toBeNumber();
expectTypeOf<Get<WithNumberKeys, 'foo[2].bar'>>().toBeUnknown();
expectTypeOf<Get<WithNumberKeys, 'foo.2.bar'>>().toBeUnknown();
// Test `readonly`, `ReadonlyArray`, optional properties, and unions with null.
interface WithModifiers {
foo: ReadonlyArray<{
bar?: {
readonly baz: {
qux: number;
};
};
abc: {
def: {
ghi: string;
};
} | null;
}>;
}
expectTypeOf<Get<WithModifiers, 'foo[0].bar.baz'>>().toEqualTypeOf<{qux: number} | undefined>();
expectTypeOf<Get<WithModifiers, 'foo[0].abc.def.ghi'>>().toEqualTypeOf<string | undefined>();