typescript - 键入一个接受对象及其属性名称的通用函数,期望 obj[propName] 是某种类型,例如 sumBy、mapBy
问题描述
这是我很抱歉尝试键入 a mapBy
:
export function mapBy<T, K = keyof T>(array: T[], key: K): T[K][] {
return array.map((item: T) => item[key]);
}
打字稿抱怨:Type 'K' cannot be used to index type 'T'. ts(2536)
我的第二种情况更棘手:
export default function sumBy<T, K = keyof T>(array: T[], key: K): number {
return array.reduce((result: number, item: T) => {
return result + item[key];
}, 0);
}
在这里,我需要以某种方式告诉 TypeScriptT
必须是一个具有number
in的对象T[K]
。
请帮助我在严格模式下正确键入此函数。
当第一个参数在具有给定名称的属性sumBy()
中没有 a 时,我希望将调用标记为类型错误。number
解决方案
您面临的主要问题是,如果编译器无法推断,或者如果有人手动指定但没有K = keyof T
给出默认规范。没有什么能阻止编译器推断或调用者手动指定一些完全不同的类型,例如,因此编译器真的不能安全地索引with 。K
keyof T
K
T
K
Date | string | Array<RegExp>
T
K
你想要的是限制使用 语法。(所以,而不是)。这修复了:K
keyof T
K extends keyof T
extends
=
mapBy()
export function mapBy<T, K extends keyof T>(array: T[], key: K): T[K][] {
return array.map((item: T) => item[key]);
}
因为sumBy()
您还需要第二个约束:您想要K extends keyof T
,但您还想要T extends Record<K, number>
whereRecord<K, V>
是一个实用程序类型,这意味着在键(或键的联合)处具有属性的类型,K
其值为 type V
。所以T extends Record<K, number>
意味着T
必须在 key 处有一个属性,K
其值为 type number
。这足以让编译器接受这result + item[key]
是一个有效的操作:
export default function sumBy<T extends Record<K, number>, K extends keyof T>(
array: T[],
key: K
): number {
return array.reduce((result: number, item: T) => {
return result + item[key];
}, 0);
}
这具有只允许参数对应于参数类型中每个元素的 -valued 属性的sumBy()
调用的预期效果:key
number
array
const arr = [{ a: 1, b: 2 }, { a: 3, b: "hello" }, { a: 6, c: true }];
console.log(sumBy(arr, "a")) // 10
sumBy(arr, "b") // error! Types of property 'b' are incompatible. string is not number
sumBy(arr, "c") // error! Types of property 'c' are incompatible. undefined is not number
推荐阅读
- powershell - 我应该在 PowerShell 中使用显式数据类型吗?
- angular - 如何修复 ERROR TypeError: t.rgb is not a function In ngx-charts heat map graph
- splunk - 为 Splunk 中的变量分配一个值并在搜索中使用该值
- python - 由于包冲突,使用 conda 安装底图 1.2.1 失败,如何解决?
- java - 通过 Gradle 下载依赖项时运行时 Eclipse 中的 NoClassDefFoundError(但在使用 Jar 文件时有效)
- flutter - FlutterView.send 在分离视图上调用,channel=plugins.flutter.io/cloud_firestore
- reactjs - 为什么我的 Web 应用程序出现未处理的拒绝错误?
- postman - 使用邮递员(不记名令牌)进行协作
- jmeter - JMeter 脚本无法正常工作
- java - 在java中将PDF文件转换为十六进制格式