You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 11:50:19