能否强制TypeScript的interface必须包含来自指定类型的全部key?
问题解答
你预想的interface FooKeys implements {[key: keyof FooType]: any}写法不可行,implements关键字仅适用于类的实现约束,不能作用于interface声明。你可以通过以下方案实现键名约束:
方案1:使用映射类型直接定义类型
这是最简便的实现方式,可直接生成和FooType键完全匹配的闭合类型,定义阶段就能限制不能多键、不能少键:
const foo = { a: 1, b: 2 }; type FooType = typeof foo; // 键完全匹配FooType的键,值类型可自定义,这里以string为例 type ConstrainedType = { [K in keyof FooType]: string; };
校验效果:
// 符合要求,校验通过 const okValue: ConstrainedType = { a: 'test1', b: 'test2' }; // 不符合要求,校验报错:缺少属性b、存在额外未知属性c const notOkValue: ConstrainedType = { a: 'test1', c: 'test3' };
方案2:使用interface配合extends实现约束
如果必须使用interface,可以让interface继承基于keyof FooType生成的Record类型:
interface ConstrainedInterface extends Record<keyof FooType, string> { // 这里可以覆盖指定单个键的类型,不会影响键名约束 // 比如写 a: number 即可把a的类型改为number }
注意:interface本身支持声明合并,属于开放类型,如果你在定义时额外添加了FooType不存在的键,TS不会在interface声明阶段报错,只有在你给该interface类型的变量赋值对象字面量时才会触发额外属性校验。
扩展场景:允许不同键对应不同值类型
如果需要给不同的键设置不同的类型,可以直接在映射类型中做条件判断:
type CustomConstrainedType = { [K in keyof FooType]: K extends 'a' ? number : boolean; }; // 上述类型等价于 { a: number; b: boolean }
内容的提问来源于stack exchange,提问作者cubabit
相关产品推荐
相关产品推荐

