条件键重映射为何无法过滤attribute为true的键?
根据类布尔属性过滤对象键的问题分析与解决
问题原因
你的代码里,Test类的attribute属性被定义为宽泛的boolean类型,而非具体的true/false字面量类型。尽管运行时test1的attribute是true、test2是false,但在TypeScript类型系统中,所有Test实例的attribute类型都是boolean。
这导致映射类型里的条件T[K]['attribute'] extends true ? never : K无法区分两个键——因为boolean并不继承自true,所以条件对两个键都返回K,最终所有键都被保留下来。
解决方案
方案一:使用泛型类推断属性字面量类型
修改Test类为泛型类,让构造函数根据传入的参数自动推断attribute的具体字面量类型:
class Test<T extends boolean = true> { readonly attribute: T; constructor(attribute?: T) { this.attribute = attribute ?? (true as T); } } type TestType2<T extends Record<string, Test<boolean>>> = { [K in keyof T as T[K]['attribute'] extends true ? never : K]: number; }; const a = { test1: new Test(), // attribute类型为true test2: new Test(false), // attribute类型为false }; type FinalTest = TestType2<typeof a>; // 结果为{ test2: number },符合预期
方案二:通过类型断言指定实例属性类型
如果无法修改Test类的定义,可以给每个实例添加类型断言,明确attribute的具体字面量类型:
class Test { readonly attribute: boolean; constructor(attribute?: boolean) { this.attribute = attribute ?? true; } } type TestType2<T extends Record<string, Test>> = { [K in keyof T as T[K]['attribute'] extends true ? never : K]: number; }; const a = { test1: new Test() as Test & { attribute: true }, test2: new Test(false) as Test & { attribute: false }, }; type FinalTest = TestType2<typeof a>; // 结果为{ test2: number }
内容的提问来源于stack exchange,提问作者machadinhos
相关产品推荐
相关产品推荐

