Почему extends возвращает false при сравнении двух интерфейсов?

#typescript #generics #typescript-generics

Вопрос:

Фон

Я пытался лучше понять, как extends это работает. Я прочитал эту превосходную статью, которая описывает A extends B как значение,

«A-это надмножество B»

Или

«A-это, возможно, более конкретная версия B»

Я также прочитал ответ SO (который я больше не могу найти), где автор описывает extends как значение,

«входит в»

Все это помогло в моем понимании.

Проблема

Я собрал несколько примеров (на игровой площадке TS) с типом утилиты, чтобы убедиться в этом самому, но нашел один случай, который я не ожидал вернуть false.

 type DoesExtend<A, B> = A extends B ? true : false;


interface MyInterface<A, B = void> {
    doSomething(input: A): B extends void ? A : A | B;
}

class MyClass1 implements MyInterface<string> {
    doSomething(input: string): string {
        return input;
    }
}

class MyClass2 implements MyInterface<string, number> {
    doSomething(input: string): string | number {
        return input;
    }
}
 

Следующие сравнения все вернули то, что я ожидал,

 DoesExtend<MyClass1, MyClass2> //true
DoesExtend<MyClass2, MyClass1> //false

DoesExtend<MyClass1, MyInterface<string>> // true
DoesExtend<MyInterface<string>, MyClass1> // true
DoesExtend<MyClass1, MyInterface<string, number>> // true
DoesExtend<MyInterface<string, number>, MyClass1> // false

DoesExtend<MyClass2, MyInterface<string>> // false
DoesExtend<MyInterface<string>, MyClass2> // true
DoesExtend<MyClass2, MyInterface<string, number>> // true
DoesExtend<MyInterface<string, number>, MyClass2> // true
 

Но при сравнении MyInterface с MyInterface одним результат оказался неожиданным,

 DoesExtend<MyInterface<string>, MyInterface<string, number>> // false - but i expected true?
DoesExtend<MyInterface<string, number>, MyInterface<string>> // false
DoesExtend<MyInterface<string, number>, MyInterface<string, number>> // true
DoesExtend<MyInterface<string, number>, MyInterface<string, number | Function>> // true
 

Вопрос

So given that the following are true,

 DoesExtend<MyClass1, MyClass2>
DoesExtend<MyClass1, MyInterface<string, number>>
DoesExtend<MyInterface<string>, MyClass2>
 

please can someone explain why the following — which would appear to me to be equivalent to the examples above and that i expected to be true — is false?

 DoesExtend<MyInterface<string>, MyInterface<string, number>>