如何在TypeScript中动态创建映射类型

时间:2018-12-28 20:41:51

标签: typescript mapped-types

给出:

ffmpeg -i samp1.mp4 -vf mpdecimate -vsync vfr out3.mp4

现在,我要动态创建一个新的type Indexed<Key extends number, Value> { [key in Key]: Value } let objLiteral: Indexed<1 | 2, string> = { 1: "one", 2: "two", } 。等效的JavaScript应该正确,但是不能编译:

Indexed<1 | 2, {x: string}>

现在,如果我在其末尾添加let mappedObj: Indexed<1 | 2, {x: string}> = Object.keys(objLiteral).reduce((acc, cur) => { acc[cur] = {x: objLiteral[cur]} return acc }, {}) ,它就可以正常工作。但这基本上只是告诉编译器“相信我,这是正确的”。有没有一种方法不需要这种重写类型系统的方法?

1 个答案:

答案 0 :(得分:2)

没有内置函数可以执行此操作,但是您可以创建一个实用程序函数,其中包含几个强制转换,但随后会为您提供正确的类型以用于任何用途:

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