Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript narrowing down within union of tuples

Tags:

typescript

Say I have a function like this:

function foo(n: number): [number, undefined] | [undefined, number] {
  if (n % 2 === 0) {
    return [n, undefined];
  }
  return [undefined, n];
}

And then calling this function like this:

function bar() {
  const [a, b] = foo(2);
  if (a === undefined) {
    return b; // TypeScript infers b as number | undefined
  }
  return a; // TypeScript infers a as number (good!)
}

Because function foo returns either tuple (number, undefined) or (undefined, number), after not passing the a === undefined check, TypeScript is able to infer that the type of a is number when returning it.

And within the if block, because a is undefined we (humans) can infer the return type of foo here as [undefined, number] hence, type of b as number. However TypeScript doesn't seem intelligent enough to be able to tell this and reports that it's number | undefined.

Is there a workaround for narrowing down on union of tuples?

like image 961
Iblisto Avatar asked Oct 12 '25 16:10

Iblisto


1 Answers

Update: The improved control-flow analysis in TypeScript 4.6 resolves the issue, so the fix below is no longer necessary. (See joematune's answer to this question.)

TypeScript's discriminating unions don't keep track of the dependency between a and b, so after you destructure the array, narrowing a won't affect the type of b. To still achieve the desired narrowing, you can directly test the array element, like this:

function bar() {
  const arr = foo(2);
  if (arr[0] === undefined) {
    const b = arr[1]
    return b; // TypeScript infers b as number (good!)
  }
  const a = arr[0]
  return a; // TypeScript infers a as number (good!)
}

TypeScript playground

like image 147
Oblosys Avatar answered Oct 16 '25 07:10

Oblosys



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!