如何为TypeScript泛型约束动态指定特定类型的属性
解决TypeScript泛型函数仅处理字符串类型属性的问题
问题分析
你需要构建一个泛型工具函数,仅允许传入对象中类型为string的属性名作为参数,但当前实现未对属性类型做限制,导致非string类型的属性也能被传入。你尝试的写法因使用了参数作为计算属性名而触发语法错误,因为TypeScript要求类型字面量中的计算属性名必须是字面量类型或唯一符号类型。
解决方案
我们可以通过定义一个辅助类型来提取对象中值类型为string的属性名,再用这个类型约束函数的path参数。
步骤1:定义辅助类型
这个类型会遍历对象的所有键,只保留对应值为string类型的键:
type StringPropertyKeys<T> = { [K in keyof T]: T[K] extends string ? K : never; }[keyof T];
步骤2:修正泛型函数
使用上述辅助类型约束path参数,确保只有string类型的属性名能被传入:
type T1 = { id: string; foo: number; bar: string[]; } const sampleData1: T1 = { bar: ["a"], foo: 42, id: "myid" } type T3 = { wrong: number; value: number; } const sampleData3 : T3 = { value : 100, wrong : 5 } // 辅助类型:提取对象中值为string类型的属性名 type StringPropertyKeys<T> = { [K in keyof T]: T[K] extends string ? K : never; }[keyof T]; const doSomething = <F>(somearg: F, path: StringPropertyKeys<F>) => { console.log(somearg[path]); } // 合法调用:传入string类型属性"id" doSomething(sampleData1, "id"); // 输出:"myid" // 非法调用:传入非string类型属性"foo",TypeScript会报错 // doSomething(sampleData1, "foo"); // 非法调用:T3中无string类型属性,TypeScript会报错 // doSomething(sampleData3, "wrong");
效果说明
- 当传入对象的string类型属性名时,函数正常执行。
- 当传入非string类型属性名时,TypeScript会在编译阶段抛出错误,提前阻止非法调用。
- 该实现兼容TypeScript 4.5.5版本,且能满足同一对象多次调用不同合法属性的需求。
内容的提问来源于stack exchange,提问作者Steve B
相关产品推荐
相关产品推荐

