TypeScript如何动态约束字符串参数为常量对象的属性值
问题描述
现有如下常量声明:
export const Actions = { VIEW: 'view', EDIT: 'edit', };
对应函数定义如下:
// 需要约束action参数只能为'view'或'edit' function insertAction(action: string): void { console.log('trust me i inserted the action'); }
需求:让action参数仅接收值为view | edit的字符串,类型需要从常量对象动态推导,不接受手动编写联合类型的方案。
尝试过的类型写法:
function insertAction(action: typeof Actions[keyof typeof Actions])
该写法未生效:调用insertAction('whatever')传入任意字符串时,TypeScript编译器和代码检查工具都不会抛出错误。
当前项目环境:
- TypeScript版本:4.4.2
- 编辑器:PHPStorm
- 框架:Next.js
依赖配置片段:
"typescript": "^4.4.2"
失效原因
TypeScript对普通对象字面量默认执行类型拓宽逻辑,上述Actions对象的属性值类型会被默认推导为通用string类型,而非'view'、'edit'两个精确的字符串字面量类型,因此typeof Actions[keyof typeof Actions]最终推导结果为string,无法对传入参数做字面量范围校验。
修复方案
给常量对象添加as const类型断言,阻止TypeScript的类型拓宽行为,让编译器将属性值推导为精确的字面量类型即可。
修改后完整代码:
// 增加as const断言,固定属性值为精确字面量类型 export const Actions = { VIEW: 'view', EDIT: 'edit', } as const; // 此时该类型推导结果为 'view' | 'edit',会严格校验传入值 function insertAction(action: typeof Actions[keyof typeof Actions]): void { console.log('trust me i inserted the action'); } // 非法调用会直接抛出类型错误 insertAction('whatever'); // 报错:类型“"whatever"”的参数不能赋给类型“"view" | "edit"”的参数 // 合法调用示例 insertAction(Actions.VIEW); insertAction('edit');
as const是TypeScript 3.4版本就已支持的语法,完全适配当前4.4.2版本的使用环境,也是常量枚举值对象定义的标准写法。
内容的提问来源于stack exchange,提问作者Kristi Jorgji
相关产品推荐
相关产品推荐

