Open maiermic opened 8 years ago
@Mouvedia Thx, I added Flow.
https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-function-parameters-bivariant
Could you provide a JS example or a link to a ressource?
We handle polymorphism with the ability to use multiple signatures. Do we need variance annotations as well? Can you show some example usage and compare with multiple signature annotation to more clearly point out advantages or disadvantages?
What do variant annotations give us that we don't already have?
@Mouvedia This is the TypeScript example (of your link) that causes a runtime error:
function trainDog(d: Dog) { ... }
function cloneAnimal(source: Animal, done: (result: Animal) => void): void { ... }
let c = new Cat();
// Runtime error here occurs because we end up invoking 'trainDog' with a 'Cat'
cloneAnimal(c, trainDog);
As the author of the example states:
This is a unsoundness resulting from the lack of explicit covariant / contravariant annotations in the type system.
We shouldn't do the same fault as TypeScript. There are better ways. For example, this is the equivalent Scala code (run online):
abstract class Animal()
case class Dog() extends Animal
case class Cat() extends Animal
object Variance extends App {
def cloneAnimal(source: Animal, done: (Animal) => Unit): Unit = {
done(source)
}
def trainDog(dog: Dog): Unit = {}
val cat = Cat()
// causes compile error:
cloneAnimal(cat, trainDog)
}
which results in a compile error
Error:(16, 20) type mismatch;
found : Dog => Unit
required: Animal => Unit
cloneAnimal(cat, trainDog)
^
since Scala defines function parameters as contravariant: Function1[-T1, +R]
. We should do the same to avoid runtime errors like in the TypeScript example, which is nothing else than JavaScript with type annotations that can be written in rtype.
Ill give you a template for your straw-man proposal because for pure javascript developers it's really hard to grasp.
+
and -
in
and out
(Microsoft/TypeScript#1394)
Declaration-site variance annotations in other languages
C#, Kotlin, Ceylon:
out
covariancein
contravarianceScala, OCaml, Flow:
+
covariance-
contravarianceWhat should we choose? (see discussion about generic types in #55 and #80)