Skip to content

Unions within/without types should be hoisted/canonicalized to improve type compatibility #14865

Closed
@weswigham

Description

@weswigham

TypeScript Version: 2.2.1

Code

type Style1 =
    | {
        type: "A";
        data: string;
    }
    | {
        type: "B";
        data: string;
    };

type Style2 = {
    type: "A" | "B";
    data: string;
}

const a: Style2 = { type: "A", data: "whatevs" };
let b: Style1;
a.type; // "A" | "B"
b.type; // "A" | "B"
b = a; // Unexpected compatibility error

Expected behavior:
No error on the assignment to b;

Actual behavior:

Type 'Style2' is not assignable to type 'Style1'.
  Type 'Style2' is not assignable to type '{ type: "B"; data: string; }'.
    Types of property 'type' are incompatible.
      Type '"A" | "B"' is not assignable to type '"B"'.
        Type '"A"' is not assignable to type '"B"'.

It's pretty clear that these types are equivalent to the human eye (only the discriminant differs between each member type of Style1, which makes it equivalent to Style2), however since TS compares memberwise when doing compatibility checking over the union, it never realizes that the overall type of the type field is identical.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DeclinedThe issue was declined as something which matches the TypeScript visionSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions