如何在TypeScript中筛选出仅含已定义且为true的optional属性的键
TypeScript类型过滤:仅保留optional属性为true的键
我需要从一个集合类型中仅保留那些optional属性已定义且值为true的键,剔除optional为false或未定义的键。当前编写的TypeScript类型实现得到的结果不符合预期:
type WithOptional = { optional?: boolean } type RecordWithOptional = Record<PropertyKey, WithOptional> type OmitUndefinedAndFalseKeys<T extends RecordWithOptional> = { [key in keyof T]: T[key]['optional'] extends false ? never : T[key]['optional'] extends undefined ? never : key }[keyof T] type test = OmitUndefinedAndFalseKeys<{ a: {optional: false} b: {optional: true} c: {} }> // 当前结果为 'b' | 'c',但预期仅为 'b'
问题原因
原类型的判断逻辑存在漏洞:当optional属性不存在时(比如c对应的{}),T[key]['optional']的类型是never,原代码的条件分支无法正确识别这种“属性未定义”的情况,导致c被误保留。
解决方案
方案1:使用映射类型的过滤语法(推荐)
利用TypeScript的映射类型as子句直接过滤符合条件的键:
type WithOptional = { optional?: boolean } type RecordWithOptional = Record<PropertyKey, WithOptional> type OmitUndefinedAndFalseKeys<T extends RecordWithOptional> = keyof { [K in keyof T as T[K] extends { optional: true } ? K : never]: T[K] } type test = OmitUndefinedAndFalseKeys<{ a: {optional: false} b: {optional: true} c: {} }> // 结果为 'b',符合预期
这个方案直接检查每个键对应的类型是否严格包含optional: true,{}和{ optional: false }都不满足该条件,因此会被过滤掉。
方案2:精确的条件判断
通过双层条件判断,先确认optional可以为true,再排除其可能为undefined的情况:
type WithOptional = { optional?: boolean } type RecordWithOptional = Record<PropertyKey, WithOptional> type OmitUndefinedAndFalseKeys<T extends RecordWithOptional> = { [K in keyof T]: true extends T[K]['optional'] ? (undefined extends T[K]['optional'] ? never : K) : never }[keyof T] type test = OmitUndefinedAndFalseKeys<{ a: {optional: false} b: {optional: true} c: {} }> // 结果为 'b',符合预期
这里第一层判断true是否属于T[K]['optional']的类型集合,第二层判断undefined是否在其中——如果是(比如c的情况),则返回never剔除该键,最终只保留optional明确为true的键。
内容的提问来源于stack exchange,提问作者zedryas
相关产品推荐
相关产品推荐

