-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Open
Labels
Description
The def-site variance (I'm not sure this term is correct, found it is used in 945df4d.) can be used for interface declarations, but it allows illegal method declarations.
This makes the type system unsound.
// @flow
class Animal {}
class Cat extends Animal {
meow() {
console.log("meow");
}
}
interface Foo<+T> { // declare T as a covariant type parameter
read(): T; // this is ok
write(val: T): void; // this should not be allowed because T is in a contravariant position
}
const foo : Foo<Cat> = {
val: new Cat(),
read(): Cat {
return this.val;
},
write(val: Cat) {
this.val = val;
}
};
(foo: Foo<Animal>); // this "up-casting" is no longer safe
(foo: Foo<Animal>).write(new Animal());
foo.read().meow(); // -> TypeError: foo.read(...).meow is not a function
In this example, the interface Foo<+T>
is declared with a method write(val: T): void
which is inconsistent with T
's covariance.
Nevertheless, Foo<Cat>
can still be up-casted to Foo<Animal>
, it can cause a runtime error.