繁体   English   中英

映射 object 类型,TypeScript 中的每个键都有泛型

[英]Mapped object type with generic per key in TypeScript

假设我有一个类型是任何两个项目的数组:一个参数列表和一个 function,其中 arguments 与参数匹配。 为了方便起见,我创建了一个可以推断泛型类型的 function。

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[] ,但如果参数与 arguments 不匹配,它不会引发类型错误。

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) => { }]
});

有没有办法 map 这个,所以每个参数都可以有它自己的通用参数列表?

type FunctionDictionary<T extends string> = {
    [K in T]: MapParamsToFunction<?> // <--- what goes here
}

TypeScript 没有存在类型来表示“某个类型XMapParamsToFunction<X> ”,所以你不能只让FunctionDictionary记录这些。 幸运的是,它确实允许从映射类型进行推断,因此您可以采用object 类型T ,其属性都是参数列表,并且 map 每个属性K到适当的MapParamsToFunction<T[K]>

type FunctionDictionary<T extends Record<keyof T, any[]>> = {
    [K in keyof T]: MapParamsToFunction<T[K]>
}

然后你的asDictionary()将从传入的FunctionDictionary<T>中推断出T object ,如下所示:

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 代码链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM