Is it possible to narrow the types of overloaded parameters without exhaustively checking each parameter in the function body?

This is now possible to a limited extent with TypeScript 4.6’s Control Flow Analysis for Dependent Parameters.

TypeScript can narrow down the types of arguments if the narrowing is done with ===. (A typeof check doesn’t appear to work, at least not yet.)

To tweak the example in the question, if the first argument, when it is a string, is abc, has no second argument, that can be detected and narrowed by TypeScript thusly:

type Fn = (...args: [number, string] | ['abc', undefined]) => void;
const fn: Fn = (abc, def) => {
    if (abc === 'abc') console.log(abc.includes('substr'));
    else console.log(def.includes('substr'));
}

The narrowing of the first argument to abc allows TS to infer that in the else, the second argument is a string, and not undefined.


It’d be great if types wider than literals could use this same technique, but they don’t work (yet) – the typeof check on the first argument fails to narrow the second argument.

type Fn = (...args: [number, string] | [string, undefined]) => void;
const fn: Fn = (abc, def) => {
    if (typeof abc === 'string') console.log(abc.includes('substr'));
    else console.log(def.includes('substr'));
}

Leave a Comment