TypeScript中能否基于JS对象键定义类型?代码问题求助
问题解决方法
你的问题出在两个核心点:
- 手动给
fields添加了Partial<Record<keyof SomeThing, boolean>>类型注解,导致TypeScript丢失了a: true、b: false的字面量类型信息,只会将所有属性识别为boolean | undefined,无法区分具体的true/false值。 Partial会让SomeThing的所有键(包括未定义的c)都成为可选属性,所以keyof typeof fields会包含a、b、c,而c的类型是undefined。
修正方案
首先,移除fields的类型注解,并用as const断言保留字面量类型:
interface SomeThing { a: string b: string c: string } // 用const断言保留字面量类型,TypeScript会准确记录{a: true, b: false} const fields = { a: true, b: false, } as const;
然后调整ExtractFields类型,只提取F中值为true的键,并映射到T的对应类型:
// 先提取F中值为true的键名 type TrueKeys<F> = { [K in keyof F]: F[K] extends true ? K : never }[keyof F]; // 再从T中筛选这些键对应的类型 type ExtractFields<T, F> = Pick<T, TrueKeys<F>>; type Result = ExtractFields<SomeThing, typeof fields>; // Result类型为:{ a: string }
原理说明
as const会让对象的属性值被推断为字面量类型(true/false),且对象本身变为只读,TypeScript不会自动拓宽类型为boolean。TrueKeys类型遍历F的所有键,将值为true的键保留,其余转为never,最后通过[keyof F]提取出所有非never的键名。Pick<T, TrueKeys<F>>从SomeThing中筛选出这些键,得到最终需要的类型。
简化合并版
如果不想拆分类型,也可以合并成一个工具类型:
type ExtractFields<T, F> = Pick< T, { [K in keyof F]: F[K] extends true ? K : never }[keyof F] >;
内容的提问来源于stack exchange,提问作者SneakyLenny
相关产品推荐
相关产品推荐

