TypeScript中简化类枚举对象类型定义的方法
TypeScript 实现类型安全伪枚举方案
直接使用as const断言+原生类型推导语法即可解决所有问题,无需重复定义类型和接口。
最终实现代码
// 仅需定义一次常量对象,无需提前声明接口/联合类型 const application = { ELECTRIC: {propA: true, propB: 11, propC: "eee"}, HYDRAULIC: {propA: false, propB: 59, propC: "hhh"}, PNEUMATIC: {propA: true, propB: 87, propC: "ppp"}, } as const; // 自动推导枚举键联合类型:"ELECTRIC" | "HYDRAULIC" | "PNEUMATIC" type Application = keyof typeof application; // 自动推导枚举值联合类型:application.ELECTRIC | application.HYDRAULIC | application.PNEUMATIC type ApplicationValue = typeof application[Application]; // 用法和原生JS完全一致 const foo = application.ELECTRIC; let bar: ApplicationValue; bar = application.HYDRAULIC; // 类型校验通过 // bar = {propA: true, propB: 1, propC: "invalid"} // 类型报错,严格限制为枚举内定义的值
对应问题逐一解决
1. 消除重复定义问题
- 不需要提前编写
Application联合类型、ApplicationProps接口,所有类型从常量对象自动推导,后续增删枚举成员时,类型会自动同步,不需要修改额外的类型代码。 - 如果确实需要获取枚举值的公共属性结构,直接通过派生类型获取即可:
type ApplicationProps = ApplicationValue,等价于之前手动写的接口定义。 - 如果需要约束枚举值必须符合固定结构,避免写错属性名/类型,使用TS 4.9+支持的
satisfies运算符即可,不会丢失类型推导:interface ApplicationProps { propA: boolean; propB: number; propC: string; } const application = { ELECTRIC: {propA: true, propB: 11, propC: "eee"}, HYDRAULIC: {propA: false, propB: 59, propC: "hhh"}, PNEUMATIC: {propA: true, propB: 87, propC: "ppp"}, } satisfies Record<string, ApplicationProps>;
2. 精准约束bar的类型
- 之前手动标注
ApplicationProps的问题在于,它仅校验对象结构,任何符合{propA: boolean, propB: number, propC: string}的对象都能赋值给bar,无法严格限制为枚举内定义的成员。 - 用
ApplicationValue(即typeof application[keyof typeof application])做类型标注时,TS会严格校验赋值内容必须是application对象下定义的成员值,完全匹配伪枚举的约束需求。
3. 简化跨文件导入
- 只需要在枚举定义文件导出常量和派生类型即可,不需要额外导出多余内容:
// enums/application.ts export const application = { /* 枚举定义 */ } as const; export type Application = keyof typeof application; export type ApplicationValue = typeof application[Application]; - 其他文件使用时,仅需引入一次常量和需要的类型即可,不需要重复编写长串类型提取语法:
其中// 其他业务文件 import { application, type ApplicationValue } from './enums/application'; let bar: ApplicationValue; bar = application.HYDRAULIC;type前缀是TS 4.5+支持的类型导入标记,导入的内容仅在类型检查阶段生效,不会被打包到运行时代码中。
内容的提问来源于stack exchange,提问作者cl10k
相关产品推荐
相关产品推荐

