TypeScript泛型函数如何限定参数为值为字符串类型的对象键?
解决TypeScript中matchBy函数的类型断言问题
我正在编写一款带组合式参数的通用过滤函数matchBy,它会返回一个匹配器函数,用于将对象<T>的指定属性(propertyName: keyof T)与字符串术语(term: string)进行比较。
原代码如下:
type Predicate<T> = (item: T) => boolean type ConditionedPredicate<T, C> = (condition: C) => Predicate<T> export const matchBy = <T>(propertyName: keyof T): ConditionedPredicate<T, string> => (term) => (item) => { const propertyValue = item[propertyName] as string const substringRegex = new RegExp(term, 'i') return Boolean(propertyValue.match(substringRegex)) }
当前问题是必须将propertyValue断言为string类型,请问如何定义propertyName的类型,使其仅允许T中值类型为string的键,从而避免该类型断言?
解决方案
通过自定义条件类型提取T中值类型为string的键,以此约束propertyName的参数类型,让TypeScript自动推断属性值的类型,无需手动断言。
- 定义
StringKeys<T>类型,筛选出T中所有值为string类型的键:
type StringKeys<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T]
这个类型的逻辑是:遍历T的所有键K,如果T[K]是string类型则保留键名K,否则设为never;最后通过[keyof T]取出所有有效键的联合类型。
- 修改
matchBy函数的propertyName参数类型为StringKeys<T>:
修改后的完整代码:
type Predicate<T> = (item: T) => boolean type ConditionedPredicate<T, C> = (condition: C) => Predicate<T> type StringKeys<T> = { [K in keyof T]: T[K] extends string ? K : never }[keyof T] export const matchBy = <T>(propertyName: StringKeys<T>): ConditionedPredicate<T, string> => (term) => (item) => { const propertyValue = item[propertyName] const substringRegex = new RegExp(term, 'i') return Boolean(propertyValue.match(substringRegex)) }
此时item[propertyName]会被TypeScript自动推断为string类型,彻底消除了类型断言的必要。
内容的提问来源于stack exchange,提问作者everm1nd
相关产品推荐
相关产品推荐

