簡體   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