Search code examples
typescriptextendsunion-types

In Typescript, how to understand 'extends' of union types?


Here is my try:

type Comb1 = "123" | "1234";
type Comb2 = "123" | "1234" | "12345";

type Res<T, U> = T extends U ? T : never;

// Res1 === "123" | "1234"
type Res1 = isExtends<Comb1, Comb2>;

// Res2 === "123" | "1234"
type Res2 = isExtends<Comb2, Comb1>;

Why Res2 is not 'never'?

And what 'extends' do in this case?


Solution

  • Change Your isExtends type to:

    type isExtends<T, U> = T extends U ? 1 : 0;
    

    then You'll see:

    type Res1 = isExtends<"123" | "1234", "123" | "1234" | "12345">; // Res1 === 1
    type Res2 = isExtends<"123" | "1234" | "12345", "123" | "1234">; // Res2 === 0 | 1
    // --------------------------------------------------------------------------^^^^^
    

    So, now return to your original case

    type isExtends<T, U> = T extends U ? T : never;
    type Res2 = isExtends<"123" | "1234" | "12345", "123" | "1234">;
    

    it results in "123" | "1234" because it's de facto ("123" | "1234") | never

    This

    isExtends<"123" | "1234" | "12345", "123" | "1234">
    

    can be expanded as:

    isExtends<"123" | "1234", "123" | "1234"> | isExtends("12345", "123" | "1234")
    

    which is

    ("123" | "1234") | never
    

    which is simply

    "123" | "1234"