Skip to content

Incorrect assignability check when using Extract (TS2322) #46413

Open
@tonygoold

Description

@tonygoold

Bug Report

🔎 Search Terms

extract assignable TS2322

🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about Generics, Assignability, and Extract.

Tested with 4.2.3, 4.3.5, 4.4.4, and 4.5.0-dev.20211018.

In 4.1.5, the example using a type alias also fails. Version 4.2 introduced Smarter Type Alias Preservation, which may explain why that example passes starting from 4.2.x.

⏯ Playground Link

Playground link with relevant code

💻 Code

I have attempted to minimize this example as much as possible. The use of Extract to define a field type appears to be significant.

type A<T> = {
    val: Extract<number | string, T>;
};
type A_number = A<number>;

function f1(x: A_number): A<number| string> {
    // Passes type checking.
    return x;
}

function f2(x: A<number>): A<number | string> {
    // Fails type checking with error TS2322:
    // Type 'A<number>' is not assignable to type 'A<string | number>'.
    //   Type 'string | number' is not assignable to type 'number'.
    //     Type 'string' is not assignable to type 'number'.
    return x;
}

🙁 Actual behavior

The type checker reports error TS2322: A<number> is not assignable to type A<string | number> because string | number is not assignable to number. It appears to be checking assignability of a field in the wrong direction, because the assignability check should be whether number is assignable to string | number.

Using a type alias for A<number> does not produce the same error. I was also not able to reproduce this error without using Extract to define a field type.

🙂 Expected behavior

The type A<number> should be assignable to type A<string | number> because it is a simple object type and number is assignable to string | number.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions