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

泛型回调中类型推断错误的问题排查与修复请求

TypeScript测量函数执行时间工具的类型系统问题

我正在编写一个通过包装函数测量函数执行时间的工具,但类型系统无法正常工作,我认为自己没出错,请问问题出在哪里以及如何修复?

function logTime(timeMs: number, name: string) {
    console.log(`Execution of "${name}" took ${timeMs} milliseconds`);
}

// 我猜问题在这里
export function measureExecutionTime<T, U>(name: string, cb: (...args: T[]) => U, handleTime = logTime) {
    return function (...innerArgs: T[]) {
        const start = new Date();
        const result = cb(...innerArgs);
        const end = new Date();
        handleTime(end.getTime() - start.getTime(), name);
        return result;
    };
}

// 这段代码应该正常工作,但报错了:val的类型是"number | number[]"。但val不可能是数组啊?
[1, 2, 3].map(measureExecutionTime("square number", val => val**2));

问题原因

你的measureExecutionTime泛型定义存在歧义:用T[]作为回调函数的剩余参数类型时,TypeScript无法确定T代表的是单个参数的类型还是参数数组的元素类型。结合map的回调函数本身可接收3个参数(当前元素、索引、原数组),TypeScript会宽泛推断T为number | number[],导致val的类型出现错误。

修复方案

方案1:仅支持单个参数的场景

如果你的工具主要用于包裹单参数函数,直接将泛型调整为明确接收单个参数:

function logTime(timeMs: number, name: string) {
    console.log(`Execution of "${name}" took ${timeMs} milliseconds`);
}

export function measureExecutionTime<T, U>(name: string, cb: (arg: T) => U, handleTime = logTime) {
    return function (arg: T) {
        const start = new Date();
        const result = cb(arg);
        const end = new Date();
        handleTime(end.getTime() - start.getTime(), name);
        return result;
    };
}

// 现在val被正确推断为number,代码正常工作
[1, 2, 3].map(measureExecutionTime("square number", val => val**2));

方案2:支持任意数量参数的通用版本

要兼容多参数函数,需要用泛型约束明确剩余参数的类型,让TypeScript正确推断参数列表:

function logTime(timeMs: number, name: string) {
    console.log(`Execution of "${name}" took ${timeMs} milliseconds`);
}

export function measureExecutionTime<T extends any[], U>(name: string, cb: (...args: T) => U, handleTime = logTime) {
    return function (...args: T) {
        const start = new Date();
        const result = cb(...args);
        const end = new Date();
        handleTime(end.getTime() - start.getTime(), name);
        return result;
    };
}

// 单参数场景正常推断
[1, 2, 3].map(measureExecutionTime("square number", val => val**2));
// 多参数场景也能正确支持
const add = measureExecutionTime("add", (a: number, b: number) => a + b);
add(1, 2); // 执行正常,类型检查通过

内容的提问来源于stack exchange,提问作者NoBullsh1t

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:45:30