Can TypeScript infer type of a discriminated union via “extracted” boolean logic?

大兔子大兔子 提交于 2021-02-05 08:17:05

问题


I have been using discriminated unions (DU) more frequently and have come to love them. I do however have one issue I can't seem to get past. If you inline a boolean check for the DU, you can rely on TypeScript (TS) to automatically infer the type for you. However, if you extract the boolean check, TS can no longer narrow to the specific subtype of the DU. I’m aware of type guards, but I’d like to know why the compiler doesn’t support extracted online checks, specifically.

Is this a known limitation? Should I file a bug/feature request?

Example here (w/ TypeScript Playground Link):

type A = { type: "A"; foo: number };
type B = { type: "B"; bar: string };
type DU = A | B;

const checkIt = (it: DU) => {
  const extractedCheck = it.type === "A";

  if (extractedCheck) {
    // it does not get narrowed
    console.log(it.foo); // Error: Property 'foo' does not exist on type 'DU'.
  }

  if (it.type === "A") {
    // but this is fine
    console.log(it.foo);
  }
};


回答1:


There is an existing feature request at microsoft/TypeScript#12184 to allow such type guard results to be "saved" into a named value to be used later. The request is open but listed as "revisit" because there's no obvious way to implement it in a performant way. The word from the lead architect of the language is:

This would require us to track what effects a particular value for one variable implies for other variables, which would add a good deal of complexity (and associated performance penalty) to the control flow analyzer. Still, we'll keep it as a suggestion.

So I wouldn't expect to see such a feature in the language anytime soon, unfortunately.


My suggestion is just to continue using your inline type check. If you have a more complex type guard situation it may be worthwhile to make a user-defined type guard function but I don't see that as an improvement for the case in your example code.


Okay, hope that helps; good luck!




回答2:


Currently nope as mentioned by @jcalz, however there's a minimal workaround that you can always apply to overcome this problem.

The trick is to make extractCheck a function that returns type predicate.
(Refer https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards)

The following is a working example:

type A = { type: "A"; foo: number };
type B = { type: "B"; bar: string };
type DU = A | B;

const checkIt = (it: DU) => {
  // Make `extractCheck` a function 
  const extractedCheck = (it: DU): it is A => it.type === "A";

  if (extractedCheck(it)) {
    console.log(it.foo);  // No error
  }
};


来源:https://stackoverflow.com/questions/61180988/can-typescript-infer-type-of-a-discriminated-union-via-extracted-boolean-logic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!