TypeScript中Array map返回undefined致Math.max传参报错解决方法
问题场景
需要从接口返回的测试运行列表中筛选出最晚的结束日期,初始实现代码如下:
const latest = Math.max(...testList.map(test => test.endedAt?.getTime()));
涉及的类型定义:
export declare class TestRunList extends Array<TestRun> { constructor(param: Array<TestRun> | number); static fromJson(data: Array<any>): TestRunList; static toJson(data: TestRunList): Array<any>; }; export declare class TestRun { // 其余属性省略 readonly endedAt?: Date; };
编译时抛出类型错误:
Argument of type 'number | undefined' is not assignable to parameter of type 'number'. Type 'undefined' is not assignable to type 'number'.
错误原因
TestRun的endedAt是可选属性,使用可选链操作符?.调用getTime()时,若某一项的endedAt为undefined,整个表达式的返回值也会是undefined。最终展开传入Math.max的参数集合类型为(number | undefined)[],但Math.max要求所有入参必须为number类型,因此触发类型校验错误。
解决方案
根据业务场景选择对应方案即可:
- 方案1(推荐,最严谨):先过滤掉
endedAt为空的无效项,再计算最大值,适合存在未结束测试项(无结束时间)的场景
// 类型谓词帮TS识别过滤后的项一定存在endedAt属性 const latestTimestamp = Math.max( ...testList .filter((test): test is TestRun & { endedAt: Date } => Boolean(test.endedAt)) .map(test => test.endedAt.getTime()) ); // 需要Date对象的话再做一次转换 const latestDate = new Date(latestTimestamp);
- 方案2:空值兜底,给缺失的结束时间传入不会影响最大值计算的极小值,适合不想额外写filter的场景
// 用负无穷兜底,Math.max计算时会自动忽略该值,不会产生NaN const latestTimestamp = Math.max(...testList.map(test => test.endedAt?.getTime() ?? -Infinity));
- 方案3:非空断言(慎用),如果业务上能100%保证所有返回的
TestRun项都有endedAt值,只是类型定义标记为可选,可以直接用非空断言跳过TS校验
const latestTimestamp = Math.max(...testList.map(test => test.endedAt!.getTime()));
注意:该方案如果运行时真的存在endedAt为空的项,会得到NaN的错误结果,无特殊把握不要用。
内容的提问来源于stack exchange,提问作者Liumx31
相关产品推荐
相关产品推荐

