Consider the following program.
interface Eq<A> {
eq(this: A, that: A): boolean;
};
class Pair<A> implements Eq<Pair<A>> {
constructor(public x: A, public y: A) {}
eq(this: Pair<A>, that: Pair<A>): boolean {
return this.x === that.x && this.y === that.y;
}
}
class Triple<A> implements Eq<Triple<A>> {
constructor(public x: A, public y: A, public z: A) {}
eq(this: Triple<A>, that: Triple<A>): boolean {
return this.x === that.x && this.y === that.y && this.z === that.z;
}
}
const eq = <A extends Eq<A>>(x: A, y: A): boolean => x.eq(y);
console.log(eq(new Pair(1, 2), new Triple(1, 2, 3)));
console.log(eq(new Triple(1, 2, 3), new Pair(1, 2)));
I would have expected the TypeScript compiler to complain about the last two lines, because you shouldn't be able to apply the eq function to two values of different types. However, the TypeScript compiler doesn't throw any type error for the above program. The result of the above program is true and false.
Why doesn't the TypeScript compiler throw a type error for the above program? How can we get it to correctly catch these kinds of type errors?