Skip to content

Regression in 3.6: Combination of union and intersection types with literal types not resolving specific types properly #33448

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ReinAkane opened this issue Sep 16, 2019 · 3 comments · Fixed by #35513
Assignees
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue

Comments

@ReinAkane
Copy link

ReinAkane commented Sep 16, 2019

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.

@ReinAkane ReinAkane changed the title 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 Sep 16, 2019
@jack-williams
Copy link
Collaborator

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 example a & c where the type of property type is '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 never which is comparable and therefore not removed from the union --- this is why you have the new errors.

Tiny example:

const x: 'a' & 'c' = 4 as any;

if (x === 'b') { // not comparable

}

const y: never = 4 as unknown as never;

if (y === 'b') { // comparable

}

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 a never property can never match a discriminant property test at runtime.

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Sep 16, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.7.0 milestone Sep 16, 2019
@jack-williams
Copy link
Collaborator

BTW I'm happy to try a PR for this, if that is helpful.

@jack-williams
Copy link
Collaborator

I've submitted a PR because I had done some experimentation anyway. Please ignore/copy/use as you see fit.

@ahejlsberg ahejlsberg added Bug A bug in TypeScript and removed Needs Investigation This issue needs a team member to investigate its status. labels Dec 5, 2019
@ahejlsberg ahejlsberg mentioned this issue Dec 5, 2019
@ahejlsberg ahejlsberg added the Fix Available A PR has been opened for this issue label Dec 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fix Available A PR has been opened for this issue
Projects
None yet
4 participants