NoBullsh1t
NoBullsh1t

Reputation: 652

Incorrect type inferred in generic callback

I'm writing a utility that measures execution times of functions by wrapping them. I have trouble getting the types to work, even though I don't think I've made a mistake. Who can tell me what the problem is and how to fix it?

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

// Here is the problem. I guess
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;
    };
}

// This should work but
// Error because val is "number | number[]". But val can't be an array, can it??
[1, 2, 3].map(measureExecutionTime("square number", val => val**2));

TS Playground

Upvotes: 0

Views: 26

Answers (1)

asportnoy
asportnoy

Reputation: 2534

Make the T parameter be the whole array of args. The issue is because the map callback function has 3 arguments (value, index, array), the last of which is an array, so TypeScript is accounting for that in the type it gives you.

export function measureExecutionTime<T extends unknown[], 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;
    };
}

Upvotes: 1

Related Questions