TypeScript 中每个键的泛型映射对象类型
Posted
技术标签:
【中文标题】TypeScript 中每个键的泛型映射对象类型【英文标题】:Mapped object type with generic per key in TypeScript 【发布时间】:2021-03-28 07:36:17 【问题描述】:假设我有一个类型,它是由两项组成的任意数组:参数列表和参数与参数匹配的函数。为了方便起见,我创建了一个可以推断泛型类型的函数。
type MapParamsToFunction<A extends any[]> = [[...params: A], (...args: A) => void]
function asMap<A extends any[]>(map: MapParamsToFunction<A>): MapParamsToFunction<A>
return map;
asMap([[],() => ]) // good
asMap([[0, "Hello World", 2], (a: number, b: string, c: number) => ]); // good
asMap([[0, "Hello World", 2], (a: number, b: number, c: number) => ]); // error
asMap([[0, "Hello World"], (a: number, b: string, c: number) => ]); // error
目前没有问题。现在,我想使用它并创建一个字典,其中每个键可以有不同的参数/参数列表。但是,我看不到让 TypeScript 在每个键上使用不同泛型的方法。
我尝试在类型上使用any[]
,但如果参数与参数不匹配,它不会引发类型错误。
type FunctionDictionary<T extends string> =
[K in T]: MapParamsToFunction<any[]>
function asDictionary<T extends string>(dict: FunctionDictionary<T>): FunctionDictionary<T>
return dict;
let obj = asDictionary(
"foo": [[0, "Hello World", 2], (a: number, b: number, c: number) => ], // no type error
"bar": [["","",""], (a: string, b: string, c: string) => ]
);
有没有办法映射这个,所以每个参数都可以有它自己的通用参数列表?
type FunctionDictionary<T extends string> =
[K in T]: MapParamsToFunction<?> // <--- what goes here
【问题讨论】:
【参考方案1】:TypeScript 没有 existential types 来表示“a MapParamsToFunction<X>
for some type X
”,因此您不能只将 FunctionDictionary
记录下来。幸运的是,它确实允许 inference from mapped types,因此您可以采用 对象类型 T
,其属性都是参数列表,并将每个属性 K
映射到适当的 MapParamsToFunction<T[K]>
:
type FunctionDictionary<T extends Record<keyof T, any[]>> =
[K in keyof T]: MapParamsToFunction<T[K]>
然后您的asDictionary()
将从传入的FunctionDictionary<T>
中推断出T
对象,如下所示:
function asDictionary<T extends Record<keyof T, any[]>>(
dict: FunctionDictionary<T>
): FunctionDictionary<T>
return dict;
你得到你想要的行为:
let obj = asDictionary(
"foo": [[0, "Hello World", 2], (a: number, b: number, c: number) => ], // error!
// --------------------------> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Types of parameters 'b' and 'args_1' are incompatible.
"bar": [["", "", ""], (a: string, b: string, c: string) => ]
);
Playground link to code
【讨论】:
您在此处的回答帮助我弄清楚了如何解决一个不同但相关的问题,该问题围绕参数化api
对象,其中键是方法名称,值是提取器函数,如 (p: Params) => Promise<Response>
。显示T
可以在T extends Record<keyof T, any[]>
中引用自身的示例特别有用。谢谢! twitter.com/davidcrespo/status/1380555171130920961以上是关于TypeScript 中每个键的泛型映射对象类型的主要内容,如果未能解决你的问题,请参考以下文章
如何使用带有 Typescript 的泛型将中继(graphql)连接映射到边缘节点
Typescript - 确保泛型属性存在于具有描述性错误的泛型类型上