typescript 实现enum枚举值定义为对象

壹 ❀ 引
最近因为有一些闲散时间,所以一直在做将Class
组件重构为typescript + hooks
组件的工作,结果今天就遇到一个有趣的问题。我们知道react Class
组件一般都会定义Component.propTypes
属性,目的在于限制组件props
类型以及某个属性是否必传等。结果在改写过程中,我发现有个属性它的定义是一个枚举:
// 枚举定义,这里借用了项目自己封装的枚举创建方法
const PaymentTypeEnum = createSimpleEnum({
SENIOR: {
value: 'pro',
type: 1,
},
TRIAL: {
value: 'trial',
type: 2
},
FREE: {
value: 'free',
type: 0,
},
PENDING: {
value: 'pending',
type: 3
}
});
// props大概的定义,type的结构可能是
Component.propTypes = {
type: PropTypes.oneOf(EnumHelper.enumValues(PaymentTypeEnum)
}
这里的type
类型就表示属于PaymentTypeEnum
其一,它可能是{value:'pro',type:1}
,也可能是{value:'free',type:0}
,而ts
是自带枚举的,所以这里我需要将其修改为ts
的枚举,让其类型推断上也能满足枚举其一。
贰 ❀ 解决Enum枚举值不能是对象
我们知道ts
中的类型其实可以分为比较抽象的原始类型,以及较为具体的字面量类型,比如我希望变量a
的值一定是个字符串,这里就能用抽象的string
表示:
const a:string = '1';
此时a
的值就必须是个字符串。而有时候我们希望某个变量的值,是按照我们预设好的值其一,这里就可以用联合类型结合字面量类型来达到效果,比如:
type NameType = 'echo' | '听风是风' | '时间跳跃';
const user: NameType = 'echo';
此时user
就只能是echo
这三个值其一,这在我们日常开发中,当为组件预设了部分固定配置时将十分有用。
所以回到开头的问题,我现在就是希望type
的类型约束,是我定义的枚举定义四个对象中的某一个,但尴尬的是,ts
枚举值定义并不支持对象,这会直接导致报错,这里我们可以借用接口与枚举达到这个效果:
// 定义枚举
enum PaymentTypeEnum {
SENIOR,
TRIAL,
FREE,
PENDING,
};
// 定义接口
interface PaymentType {
[PaymentTypeEnum.SENIOR]: {
value: 'pro';
type: 1;
};
[PaymentTypeEnum.TRIAL]: {
value: 'trial';
type: 2;
};
[PaymentTypeEnum.FREE]: {
value: 'free';
type: 0;
};
[PaymentTypeEnum.PENDING]: {
value: 'pending';
type: 3;
};
}
// 组件props接口定义
interface ComponentPropsType {
type: PaymentType[PaymentTypeEnum]
}
我们来做个试验验证下,比如我现在要定义payment
值为:
const payment: ComponentPropsType = {
type: {
value: 'pendings',// Type '"pendings"' is not assignable to type '"pro" | "trial" | "free" | "pending"'.
type: 4 // Type '4' is not assignable to type '0 | 1 | 2 | 3'.
}
}
可以看到,不管是value
还是type
,只要我们属性定义错误,或者额外多添加属性,都能正确达到错误提示。其实到这里我们就已经达到了枚举值是对象字面量类型的效果了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2020-05-13 JS leetcode 至少是其他数字的两倍的最大数 解答思路分析
2020-05-13 JS leetcode 两数之和解答思路分析