On this scenario:
type Type = {
a: string;
b: string;
} | {
a: number;
b: number;
};
const func = ({a, b}: Type): string => {
if (typeof a === 'string') {
return b;
}
return 'w/e';
}
func({a: 1, b: 'w/e'});
I get an error on return b;
stating
Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
From what I understand by the error, Typescript interprets the Type type as
type Type = {
a: string | number;
b: string | number;
};
, but even if that is the case, why can't I call the func
function with a string and a number?
The error on the call states
Argument of type '{ a: number; b: string; }' is not assignable to parameter of type 'Type'.
Type '{ a: number; b: string; }' is not assignable to type '{ a: number; b: number; }'.
Types of property 'b' are incompatible.
Type 'string' is not assignable to type 'number'.
(ts version: 4.7.2)
- Edit after UnholySheep's comment:
The function call with the wrong types was just to test my hypothesis on why I get the previous error. Why do I get an error at return b;
is what I don't understand.
CodePudding user response:
TS cannot tract the relationship of a
and b
after you destruct them, so they both be inferred string | number
. TS 4.6 introduced a limited control flow analysis for destructing, which only applies to discriminated union.
CodePudding user response:
Ok, the answer is Discriminated Unions
.
I have to use a discriminant, a common property in each element of the union.
That, discriminant, property:
- Has to be a primitive type, and
- Has to have a specific value and not that value's type. e.g.
isPrimary: true
, notisPrimary: boolean
.
Then I can check for that property's value to assume the other properties' types.
Also, in Typescript versions < 4.6, If i have an object with a type specified as above, If i destructure it, then the new variables are considered independent and I will continue getting an error similar to the initial example. Destructuring works in version 4.6 or higher.
Helpful links:
- @Austaras's link to Microsoft's post announcing destructuring support
- Understanding Discriminated Unions
- Typescript's Singleton types
Thank you @Austaras and @coglialoro