TypeScript函数非数值入参测试问题:报错处理与合理性探讨
TypeScript函数类型校验与测试问题解答
问题描述
现有如下TypeScript函数,根据CVSS v3分数返回对应的颜色类名:
const cvssV3Color = (cvssV3: number): any => { if (cvssV3) { if ((cvssV3 > 0) && (cvssV3 <= 3.9)) { return 'low-color' } else if ((cvssV3 >= 4) && (cvssV3 <= 6.9)) { return 'medium-color' } else if ((cvssV3 >= 7) && (cvssV3 <= 8.9)) { return 'high-color' } else if ((cvssV3 >= 9) && (cvssV3 <= 10)) { return 'critical-color' } throw new Error("Not valid range is provide") } };
使用Vitest+Vue.js 3编写测试用例,希望验证传入无效数据类型时函数抛出错误,但由于函数入参被定义为number类型,TypeScript会提示类型错误:
it("Should throw error when type of input range is not valid",()=>{ const rangeCondition = '1' const resultFn = ()=>{ cvssV3Color(rangeCondition) } expect(resultFn).toThrow() })
解决方案
1. 增加运行时类型校验(推荐)
TypeScript的类型约束仅在编译阶段生效,运行时不会自动校验类型。如果需要函数在运行时处理无效类型,需要修改函数定义,放宽入参类型并加入类型校验逻辑:
const cvssV3Color = (cvssV3: unknown): string => { // 先校验输入类型 if (typeof cvssV3 !== 'number') { throw new Error("Invalid input type"); } // 再校验分数范围 if (cvssV3 > 0 && cvssV3 <= 3.9) { return 'low-color'; } else if (cvssV3 >= 4 && cvssV3 <= 6.9) { return 'medium-color'; } else if (cvssV3 >= 7 && cvssV3 <= 8.9) { return 'high-color'; } else if (cvssV3 >= 9 && cvssV3 <= 10) { return 'critical-color'; } else { throw new Error("Not valid range is provided"); } };
修改后,函数会先检查输入是否为number类型,不符合则直接抛出错误,同时TypeScript也允许传入unknown类型的参数,测试用例可以正常运行。
2. 测试时绕过TypeScript类型检查
如果不想修改函数的类型定义(比如函数仅在纯TS环境中使用,但需要模拟异常场景),可以在测试代码中用// @ts-expect-error注释让TypeScript忽略类型错误:
it("Should throw error when type of input range is not valid", () => { const rangeCondition = '1'; const resultFn = () => { // @ts-expect-error 故意传入错误类型以测试运行时行为 cvssV3Color(rangeCondition); }; expect(resultFn).toThrow(); });
也可以使用类型断言强制转换类型:cvssV3Color(rangeCondition as unknown as number),但// @ts-expect-error更清晰,明确表示这是故意的类型违规。
测试合理性分析
针对预定义类型的入参编写这类测试是否合理,取决于函数的使用场景:
- 必要场景:如果函数会被编译为JavaScript在非TS环境中调用,或者接收来自API、用户输入等未经过TypeScript类型校验的数据,这类测试非常关键。因为编译后的JS代码没有类型约束,必须靠运行时校验和测试来保证函数的健壮性。
- 可选场景:如果函数仅在纯TypeScript项目内部使用,且所有调用方都严格遵循类型定义,这类测试的必要性较低。但作为防御性编程的补充,测试可以覆盖一些意外情况(比如隐式类型转换、第三方库返回不符合预期的类型等)。
内容的提问来源于stack exchange,提问作者amir tbi
相关产品推荐
相关产品推荐

