簡體   English   中英

如何在TypeScript中動態創建映射類型

[英]How to dynamically create mapped type in TypeScript

鑒於:

type Indexed<Key extends number, Value> {
    [key in Key]: Value
}

let objLiteral: Indexed<1 | 2, string> = {
    1: "one",
    2: "two",
}

現在,我要動態創建一個新的Indexed<1 | 2, {x: string}> Indexed<1 | 2, {x: string}> 等效的JavaScript應該正確,但這不能編譯:

let mappedObj: Indexed<1 | 2, {x: string}> =
    Object.keys(objLiteral).reduce((acc, cur) => {
        acc[cur] = {x: objLiteral[cur]}
        return acc
    }, {})

現在,如果我將其添加as Indexed<1 | 2, { x: string }> ,它將可以正常工作as Indexed<1 | 2, { x: string }> as Indexed<1 | 2, { x: string }>到結尾。 但這基本上只是告訴編譯器“相信我,這是正確的”。 有沒有一種方法可以執行此操作,而無需以這種方式覆蓋類型系統?

沒有內置函數可以執行此操作,但是您可以創建一個實用函數,該函數內部具有幾個強制類型轉換,但是隨后將為您提供正確的類型以用於任何用法:

function mapObject<
    TObject extends {},
    TItem,
    TKey extends keyof TObject = keyof TObject
>(
    obj: TObject,
    callback: (value: TObject[TKey], key: TKey, obj: TObject) => TItem
): { [K in TKey]: TItem }
{
    const result = {} as { [K in TKey]: TItem }
    for (let key in obj) {
        const k = key as any as TKey
        if (obj.hasOwnProperty(key)) {
            result[k] = callback(obj[k], k, obj)
        }
    }
    return result;
}

let mappedObj = mapObject(objLiteral, x => ({ x }));
mappedObj[1].x; // has type "string" as expected

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM