Description
TypeScript Version: 3.6.2 and 3.6.3
Search Terms: union types, intersection types, literal types
Code
type a = {
type: 'a',
data: string
}
type b = {
type: 'b',
name: string
}
type c = {
type: 'c',
other: string
}
type abc = a | b | c;
function f(problem: abc & (b | c)) {
if (problem.type === 'b') {
console.log(problem.name);
} else {
console.log(problem.other);
}
}Expected behavior:
TypeScript not to complain about the typings.
Actual behavior:
In the f function, TypeScript says that problem may not have name because type Property 'name' does not exist on type 'a & c', but a and c are mutually exclusive types and therefore not possible. It also complains that problem may not have other because Property 'other' does not exist on type 'a & b', but due to the if/else, it's not possible for problem to be of type b, and in fact the only possible type for it is c.
Playground Link: Since the playground is still on 3.5.1, this issue is not reproducible there. Here's a link to the example I posted above in the playground (though it is passing): https://www.typescriptlang.org/play/#code/C4TwDgpgBAhlC8UDeAoK6qkgLigchjwBo0MATGYGXAZ2ACcBLAOwHMUBfFLaAIwWSl0PXHl7EhUZjAC2EWgxbsuPKAGMBqDJnDz8aidoD2wABYR6Cpm07ddsXhsRwAPlH5u1AbhQAzAK7MasCMRsxQvgAUYPRGvAA2EDK4MI5QAGRQkR7qAJS5gtqMvlkxcYkyAHSq8LX44gVa2hhqYTRGiZXxRqzRsQlJldJyuT7aHFAQ8TTQTc3qbR0QXT195YMm5vSjklxcQA
Related Issues: #33101 looked like it might be related, can't quite tell.
Activity
[-]Regression in 3.6.3: Combination of union and intersection types with literal types not resolving specific types properly[/-][+]Regression in 3.6: Combination of union and intersection types with literal types not resolving specific types properly[/+]jack-williams commentedon Sep 16, 2019
Most likely triggered by #31838.
The type
abc & (b | c)is creating a load of types that logically cannot exist because they contain a property that intersects disjoint types, for examplea & cwhere the type of propertytypeis'a' & 'c'.Prior to #31838 these propertys would remain as unreduced intersections that are incomparable to the discriminated property, and are therefore removed from the union type. Now they are reduced to
neverwhich is comparable and therefore not removed from the union --- this is why you have the new errors.Tiny example:
Under 3.5 these two behave differently, now they behave the same.
It seems like the discriminant logic needs to change, perhaps to remove things that are incomparable or
never, which makes sense because aneverproperty can never match a discriminant property test at runtime.jack-williams commentedon Sep 16, 2019
BTW I'm happy to try a PR for this, if that is helpful.
jack-williams commentedon Sep 18, 2019
I've submitted a PR because I had done some experimentation anyway. Please ignore/copy/use as you see fit.