Why does extends return false when comparing two interfaces?

Viewed 30

Background

I've been trying to get a better understanding of how extends works. I read this excellent article that describes A extends B as meaning,

'A is a superset of B'

Or

'A is a possibly-more-specific version of B'

I also read an SO answer (that i can no longer find) where the author describes extends as meaning,

'goes into`

All of this helped in my understanding.

Problem

I put together some examples (in the TS playground) with a utility type to see for myself, but found one case that i didn't expect to return 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;
    }
}

The following comparisons all returned what i expected,

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

But when comparing MyInterface with MyInterface one result was unexpected,

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

Question

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>>
0 Answers
Related