如何在Jest测试中将TypeScript类型转为值以校验键长度?
TypeScript类型转值用于Jest键长度校验
给定TypeScript类型定义:
export type Events = { LOGIN: undefined NAVIGATION: { screen: string } SUPPORT: { communication_method: 'chat' | 'email' | 'phone' } }
想要写Jest测试确保Events的所有键长度不超过45字符,写出的测试代码却触发TypeScript报错:
it('is compliant to event limitations', () => { Object.keys(Events).forEach((key) => { expect(key.length).toBeLessThan(45) }) })
报错信息:
'Events' only refers to a type, but is being used as a value here.
下面是几种优雅的解决方式:
1. 绑定类型与值(推荐)
直接重构代码,先定义一个常量对象,再基于这个对象生成类型。这样既能拿到可用于测试的实际值,又能保留类型的类型检查能力:
// 定义常量,用as const锁定类型 export const events = { LOGIN: undefined, NAVIGATION: {} as { screen: string }, SUPPORT: {} as { communication_method: 'chat' | 'email' | 'phone' } } as const; // 基于常量生成原有的Events类型 export type Events = typeof events;
测试代码直接使用这个常量:
it('is compliant to event limitations', () => { Object.keys(events).forEach((key) => { expect(key.length).toBeLessThan(45) }) })
2. 手动维护键数组+类型断言
如果不想改动原类型定义,可以手动创建包含所有Events键的数组,并用类型断言让TypeScript校验数组元素是否与类型键完全匹配。这样一旦类型的键发生变化,TypeScript会直接报错,避免测试遗漏:
// TypeScript会校验这个数组的元素是否都是Events的键 const eventKeys = ['LOGIN', 'NAVIGATION', 'SUPPORT'] as Array<keyof Events>; it('is compliant to event limitations', () => { eventKeys.forEach((key) => { expect(key.length).toBeLessThan(45) }) })
这种方式适合类型不频繁变动的场景,不用重构原有类型代码。
3. 编译时校验键长度(提前拦截错误)
可以写一个类型工具,在编译阶段就检查所有键的长度是否符合要求,不用等到测试运行才发现问题:
// 类型工具:检查每个键的长度是否小于45 type ValidateKeyLength<T> = { [K in keyof T]: K extends string ? (K['length'] extends number ? (K['length'] < 45 ? unknown : never) : never) : never }; // 触发校验:如果有键长度超过44,这里会直接报错 type _CheckEventKeys = ValidateKeyLength<Events>;
这种方式可以和前两种方案结合使用,既在编译阶段拦截错误,又在测试中做最终校验。
内容的提问来源于stack exchange,提问作者Norfeldt
相关产品推荐
相关产品推荐

