如何基于字符串联合类型创建键范围固定、属性类型可自定义的对象类型
如何基于字符串联合类型创建键范围固定、属性类型可自定义的对象类型
嘿,我明白你的需求了——你有一个字符串联合类型Keys,想要创建一个对象类型,它的键只能是这个联合里的成员,同时每个键的类型可以自己灵活指定,还得能阻止添加联合外的键对吧?
其实你已经摸到门道了,你写的{ [K in Keys]: any }就是TypeScript里的映射类型,它会把联合类型里的每个成员都转成对象的键。不过要实现“自定义每个键的类型+禁止额外键”的需求,咱们可以调整下写法,下面给你几种实用的方案:
方案1:映射类型+条件类型(批量指定类型)
如果你的键对应的类型有规律,可以用条件类型在映射里直接分配:
type Keys = 'a' | 'b' | 'c'; // 给每个键指定对应类型,同时确保键只能来自Keys type MyType = { [K in Keys]: K extends 'a' ? string : K extends 'b' ? number : boolean; };
这样MyType最终就是{ a: string; b: number; c: boolean },而且你没法加任何不在Keys里的键。
方案2:约束类型+交叉类型(手动指定每个键)
如果你想更直观地手动写每个键的类型,同时强制只能用Keys里的键,可以先定义一个约束类型,再用交叉类型覆盖默认值:
type Keys = 'a' | 'b' | 'c'; // 第一步:定义约束——必须包含所有Keys的键,值默认any type KeysConstraint = { [K in Keys]: any }; // 第二步:交叉自定义类型,覆盖每个键的具体类型 type MyType = KeysConstraint & { a: string; b: number; c: boolean; // d: any; // 这里加的话会直接报错,因为d不在Keys里! };
这种方式很灵活,你可以清晰地给每个键指定不同类型,TypeScript会自动检查你有没有加额外的键。
方案3:用satisfies关键字(TypeScript 4.9+)
如果你用的是TS 4.9及以上版本,satisfies关键字会更简洁,它能在不改变类型结构的前提下,检查你的类型是否符合约束:
type Keys = 'a' | 'b' | 'c'; type MyType = { a: string; b: number; c: boolean; // d: any; // 加上这行会报错,因为不符合Record<Keys, any>的约束 } satisfies Record<Keys, any>;
这里Record<Keys, any>是TypeScript内置的工具类型,和你写的{ [K in Keys]: any }效果一样,用它更省心。
核心思路就是利用映射类型(或者内置的Record)来限定键的范围,然后通过交叉类型、条件类型或者satisfies来自定义每个键的具体类型,这样既满足了键的范围限制,又能灵活指定值的类型。
备注:内容来源于stack exchange,提问作者Islam Y-
相关产品推荐
相关产品推荐

