简体   繁体   中英

Typescript narrowing down within union of tuples

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 number | undefined .

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

TypeScript's discriminating unions don't keep track of the dependency between a and b , so after you deconstruct 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM