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'));
}