[英]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.