TypeScript泛型如何正确指定仅选取对象中值为函数类型的键
解决方案
你可以通过自定义映射类型筛选出对象中所有值为函数类型的键,再用该类型约束入参键名范围,TypeScript 就能自动推断键对应的值一定是函数类型,无需额外强制类型转换。
第一步:定义工具类型
// 工具类型:提取对象中所有值为函数类型的键 type FunctionKeys<T> = { [K in keyof T]: T[K] extends Function ? K : never }[keyof T]
第二步:修改addFunction泛型定义
const functionStore: Array<Function> = []; // 泛型约束第二个参数的键必须对应对象中的函数类型属性 const addFunction = <Obj, Key extends FunctionKeys<Obj>>( obj: Obj, ...extractFunction: Key[] ) => { for (const key of extractFunction) { // 此时TS可自动推断obj[key]为Function类型,无类型错误 functionStore.push(obj[key]); } };
测试效果
const obj = { msg: 'Welcome!', test() { console.log('Hello!!'); }, doNoAdd() { console.log('Do not add!'); }, otherTest() { console.log('Other test!!'); } }; // 合法调用,无类型错误 addFunction(obj, 'test', 'otherTest'); // 错误调用示例:传入非函数属性的键'msg'会直接触发TS类型报错 // addFunction(obj, 'msg')
实现原理
FunctionKeys<T>是TypeScript映射类型的典型用法:遍历对象T的所有键,对每个键判断对应值是否继承自Function类型,符合条件则保留键名作为类型,否则返回never。最后通过索引访问[keyof T]将所有符合条件的键名组合成联合类型。- 给addFunction新增第二个泛型参数Key,约束其必须是传入对象Obj的FunctionKeys子类型,即可从类型层面限制入参的键名只能对应函数类型属性,TS自然可以确定
obj[key]的类型一定是Function,无需任何强制类型转换。
内容的提问来源于stack exchange,提问作者Grizzly
相关产品推荐
相关产品推荐

