TypeScript:如何从接口提取属性类型为指定类型的属性名类型?
问题解答
TypeScript有没有内置方法实现这个需求?
TypeScript没有直接提供这种按属性类型筛选键的内置工具,但可以用它自带的keyof、条件类型这些基础语法,自己写一个Select类型来实现需求。
具体实现方式
你可以定义一个通用的Select工具类型,遍历目标类型的所有属性,把类型匹配的属性名挑出来组成联合类型:
// 自定义Select工具类型 type Select<T, TargetType> = { [Key in keyof T]: T[Key] extends TargetType ? Key : never }[keyof T] // 你的Filters接口 export interface Filters { field1: string[] field2: string[] field3: boolean field4: number } // 用Select筛选类型为string[]的属性 export type MultivalueFields = Select<Filters, string[]> // 此时MultivalueFields的类型为 'field1' | 'field2'
代码逻辑说明
keyof T:先获取T所有属性名组成的联合类型,这里就是'field1' | 'field2' | 'field3' | 'field4'。[Key in keyof T]:逐个遍历每个属性名Key,检查对应的属性类型T[Key]。T[Key] extends TargetType ? Key : never:如果属性类型符合目标类型,就保留这个属性名;不符合则返回never(一种会被自动忽略的特殊类型)。[keyof T]:最后提取临时对象里的所有值,never会被过滤掉,剩下的就是符合条件的属性名联合类型。
进阶:严格类型匹配
如果需要严格区分string[]和readonly string[]这类细微差异,可以自定义Equal类型做精确判断:
// 自定义Equal类型,判断两个类型是否完全一致 type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false // 严格匹配的SelectStrict类型 type SelectStrict<T, TargetType> = { [Key in keyof T]: Equal<T[Key], TargetType> extends true ? Key : never }[keyof T] // 使用示例 export type StrictMultivalueFields = SelectStrict<Filters, string[]> // 结果依然是 'field1' | 'field2'
内容的提问来源于stack exchange,提问作者Some random IT boy
相关产品推荐
相关产品推荐

