有没有可能提取类型形式的对象提供一个路径,它在N大小的元组格式。如果是这样,如何?例子我有什么想法:
type ExtractType<O, T> = ...; type Foo = ExtractType<{ a: { b: number } }, ['a', 'b']> // I expect Foo type to be number
p1iqtdky1#
下面的naive版本,naive表示我不限制path为对象的有效路径,如果key path无效,返回类型将是unknown。
unknown
type ExtractType<O, T extends Array<any>> = { [K in keyof O]: ((...a: T) => any) extends ((a: any, ...args: infer Tail) => any) ? Tail['length'] extends 0 ? O[K] : ExtractType<O[K], Tail> : never }[T[0]] // example Foo is number type Foo = ExtractType<{ a: { b: { c: {d: number} } }, g: string }, ['a', 'b', 'c', 'd']>
它是递归类型,所以深度不受限制。需要考虑的几件事:
((...a: T) => any) extends ((a: any, ...args: infer Tail) => any)
Tail['length'] extends 0 ? O[K] : ExtractType<O[K], Tail>
lndjwyie2#
如果你想把自己的深度限制在2,所以只用一个元组作为路径,你可以使用下面的类型定义:
type ExtractType< O extends { [K1 in T[0]]: { [K2 in T[1]]: any } }, T extends [string, string] > = O[T[0]][T[1]]; type Foo = ExtractType<{ a: { b: number } }, ['a', 'b']> // number
Playground链接
mnemlml83#
Maciej Sikora的答案对我不起作用。更改字符串的数组可以更容易地在Typescript中递归遍历:
export type ExtractType<T, K extends string = string> = K extends `${infer KHead}.${infer KTail}` ? (KHead extends keyof T ? ExtractType<T[KHead], KTail> : never) : (K extends keyof T ? T[K] : never);
所以你可以称之为:
ExtractType<{ a: { b: number } }, 'a.b'> // = number
3条答案
按热度按时间p1iqtdky1#
下面的naive版本,naive表示我不限制path为对象的有效路径,如果key path无效,返回类型将是
unknown
。它是递归类型,所以深度不受限制。需要考虑的几件事:
((...a: T) => any) extends ((a: any, ...args: infer Tail) => any)
这部分用来切掉元组的头,递归地处理尾。这意味着我们遍历对象,直到带键的元组为空。每次递归调用都少处理一个元素。Tail['length'] extends 0 ? O[K] : ExtractType<O[K], Tail>
-仅当我们位于键元组的末尾时才采用值类型lndjwyie2#
如果你想把自己的深度限制在2,所以只用一个元组作为路径,你可以使用下面的类型定义:
Playground链接
mnemlml83#
Maciej Sikora的答案对我不起作用。更改字符串的数组可以更容易地在Typescript中递归遍历:
所以你可以称之为: