TypeScript能否强制检查Record的所有Enum值是否完整?
如何让TypeScript检查Record的值包含所有枚举成员?
当你定义字符串枚举后,用Record<Test, string>约束对象时,TypeScript会自动检查对象是否包含所有枚举成员作为键——比如下面的代码会直接报错,提示你补全another键:
enum Test { some = 'some', another = 'another', } const test: Record<Test, string> = { some: 'string' }
但反过来,要是你需要约束对象的值必须覆盖所有枚举成员(比如序列化/解析场景),用Record<string, Test>就不管用了——下面的代码不会报错,但实际上只包含了Test.some:
enum Test { some = 'some', another = 'another', } const test: Record<string, Test> = { some: Test.some }
下面给你几种实现编译时检查的方法:
方法1:自定义类型强制值覆盖所有枚举成员
你可以借助TypeScript的工具类型,定义一个约束类型,确保对象的值的联合类型完全等于枚举的所有成员:
enum Test { some = 'some', another = 'another', } // 获取枚举的所有值的联合类型 type TestValues = typeof Test[keyof typeof Test]; // 定义约束类型:如果值的联合缺少枚举成员,就会触发编译报错 type RecordWithAllEnumValues = Record<string, Test> & { _check: Exclude<TestValues, ReturnType<typeof test[keyof typeof test]>> extends never ? unknown : never; }; // 正确示例:包含所有枚举值,无报错 const test: RecordWithAllEnumValues = { some: Test.some, another: Test.another }; // 错误示例:缺少Test.another,编译报错 const test2: RecordWithAllEnumValues = { some: Test.some };
方法2:用工具函数结合编译+运行时检查
如果需要同时做编译时和运行时的双重检查,可以写个辅助函数:
enum Test { some = 'some', another = 'another', } // 编译时约束类型 type AllEnumValues = Record<string, Test>; // 运行时检查函数:确保枚举的所有值都在对象中存在 function ensureAllEnumValues(obj: AllEnumValues): obj is AllEnumValues { const enumValues = new Set(Object.values(Test)); const objValues = new Set(Object.values(obj)); for (const val of enumValues) { if (!objValues.has(val)) { throw new Error(`对象缺少枚举值:${val}`); } } return true; } // 使用示例:先过编译检查,再做运行时验证 const test = { some: Test.some, another: Test.another }; ensureAllEnumValues(test); // 正常通过 const test2 = { some: Test.some }; ensureAllEnumValues(test2); // 运行时抛出错误
方法3:利用satisfies简化检查(TS 4.9+)
如果你用的是TypeScript 4.9及以上版本,可以结合satisfies运算符和类型约束:
enum Test { some = 'some', another = 'another', } type TestValues = typeof Test[keyof typeof Test]; // 定义约束类型 type EnsureAllValues = Record<string, Test> & { _check: Exclude<TestValues, Test> extends never ? unknown : never; }; // 使用satisfies确保类型符合要求 const test = { some: Test.some, another: Test.another } satisfies EnsureAllValues; // 正常 const test2 = { some: Test.some } satisfies EnsureAllValues; // 编译报错
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

