-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path270-typed-get.ts
62 lines (55 loc) · 1.62 KB
/
270-typed-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
/**
* 270 - Typed Get
*
* The [`get` function in lodash](https://lodash.com/docs/4.17.15#get) is a quite convenient helper for accessing nested values in JavaScript. However, when we come to TypeScript, using functions like this will make you lose the type information. With TS 4.1's upcoming [Template Literal Types](https://devblogs.microsoft.com/typescript/announcing-typescript-4-1-beta/#template-literal-types) feature, properly typing `get` becomes possible. Can you implement it?
*
* For example,
*
* ```ts
* type Data = {
* foo: {
* bar: {
* value: 'foobar',
* count: 6,
* },
* included: true,
* },
* hello: 'world'
* }
*
* type A = Get<Data, 'hello'> // 'world'
* type B = Get<Data, 'foo.bar.count'> // 6
* type C = Get<Data, 'foo.bar'> // { value: 'foobar', count: 6 }
* ```
*
* Accessing arrays is not required in this challenge.
*
*/
/* _____________ Your Code Here _____________ */
type Get<T, K extends string> = K extends keyof T
? T[K]
: K extends `${infer Key}.${infer Rest}`
? Key extends keyof T
? Get<T[Key], Rest>
: never
: never
/* _____________ Test Cases _____________ */
import type { Equal, Expect } from '@type-challenges/utils'
type cases = [
Expect<Equal<Get<Data, 'hello'>, 'world'>>,
Expect<Equal<Get<Data, 'foo.bar.count'>, 6>>,
Expect<Equal<Get<Data, 'foo.bar'>, { value: 'foobar', count: 6 }>>,
Expect<Equal<Get<Data, 'foo.baz'>, false>>,
Expect<Equal<Get<Data, 'no.existed'>, never>>,
]
type Data = {
foo: {
bar: {
value: 'foobar'
count: 6
}
included: true
}
'foo.baz': false
hello: 'world'
}