问题
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