只要它在运行时工作,您就可以can告诉 TypeScript 如何使用重命名键映射类型:
type RenameKeys<T, KS extends Record<keyof KS, keyof T>> = {[K in keyof KS]: T[KS[K]]};
function getProperties<T, KS extends Record<keyof KS, keyof T>>(
obj: T,
keys: KS
): RenameKeys<T, KS> {
const def = {} as RenameKeys<T, KS>;
return (Object.entries(keys) as Array<[keyof KS, any]>)
.reduce((result, [key, value]) => {
result[key] = getProperty(obj, value);
return result;
}, def);
}
这应该像您在类型系统中所期望的那样运行。亮点:类型keys
给出一个名为的类型参数KS
,这被限制为Record<keyof KS, keyof T>
,这或多或少意味着“我不关心键是什么,但属性类型必须是来自T
”。那么,RenameKeys<T, KS>
走过的钥匙KS
并从中提取财产类型T
与他们有关。
最后,我需要做一些类型断言......def
is RenameKeys<T, KS>
。的类型value
in [key, value]
我刚刚做了any
,因为类型系统很难验证这一点result[key]
将是正确的类型。所以这有点捏造了实现类型的安全性......但是调用者getProperties()
应该高兴:
const {a2, n2} = getProperties(person, {
a2: 'name',
n2: 'age'
});
// a2 is string, n2 is number.
Playground 代码链接