typescript - 如何使用打字稿中的查找来推断类型化的 mapValues?
问题描述
如同:
我正在寻找一个通用对象,它接收任意键的映射以查找值,并返回具有类型值的相同键(如类型化 _.mapValues)。
从对象获取单一类型属性的能力已被记录并有效。使用数组,您需要将重载硬编码为类型化元组,但对于对象,我会收到“重复字符串索引签名”错误。
export interface IPerson {
age: number;
name: string;
}
const person: IPerson = {
age: 1,
name: ""
}
function getProperty<T, K extends keyof T>(o: T, name: K): T[K] {
return o[name];
}
const a = getProperty(person, 'age');
// a: number
const n = getProperty(person, 'name');
// n: string
function getProperties<T, K extends keyof T>(obj: T, keys: { [key: string]: K }) {
const def: { [key: string]: T[K] } = {};
return Object.entries(keys).reduce((result, [key, value]: [string, K]) => {
result[key] = getProperty(obj, value);
return result;
}, def);
}
const { a2, n2 } = getProperties(person, {
a2: 'name',
n2: 'age'
});
// Result:
// {
// a2: string | number,
// n2: string | number
// }
// What I'm looking for:
// {
// a2: string,
// n2: number'
// }
这如何用打字稿实现?
解决方案
只要它在运行时工作,你就可以告诉 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.
推荐阅读
- android - 是否可以在 Android Studio 中使用已发布的签名 APK 构建 App Bundle?我想将 apk 迁移到 Play 商店的应用程序包
- jmeter - 将 JMeter 与 ZAP 工具集成
- angular - 如何在 TypeScript 中同步下拉菜单?
- c# - 如何在应用程序代码中删除 app.config
- ios - 在蒙面的 UIView 周围添加阴影
- machine-learning - 在使用全卷积网络的语义分割中,为什么交叉熵损失优于 L1 或 L2 损失?
- android - android中画布文本的椭圆大小
- node.js - 如何修复 npm ERR!缺少脚本:从反应开始
- ios - CocoaPods 找不到 pod“Alamofire 5.0.0-rc.2”的兼容版本
- visual-studio - 如何降级 Visual Studio 2017 版本?