Skip to content

def-site variance does not prohibit illegal method declarations for interfaces #4287

@susisu

Description

@susisu

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions