-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic type parameter in plain function is checked contravariantly. #16797
Comments
The rule applies to function parameters that are functions. So it applies to trainDog which you are passing a a parameter to cloneAnimal which expects a function that takes a parameter result that is a subtype of Animal. Your function trainDog takes a parameter d of type Dog. Callback parameters are checked bivariantly it is their return values that are checked covariantly, you are just returning void in both. So you need to change Done so the parameter name matches, and the inheritance relation wont work because of bivariance checking of callback parameters |
How about this reduced example? Without callback at all. Note, enabling class Animal { }
class Dog extends Animal {
bark(): void {}
}
type TrainDog = (d: Dog) => void
type TrainAnimal = (a: Animal) => void
type TrainAnimalGen = <A extends Animal>(a: A) => void
declare var trainDog: TrainDog
declare var trainAnimal: TrainAnimal
declare var trainAnimalGen: TrainAnimalGen
trainAnimal = trainDog // ok
trainAnimalGen = trainDog // error |
After digging deeper, I'm sure this is caused by stricter generic comparison, not stricter variance check. In the function train<A extends Animal>(a: A) {
a = new Dog // error, of course
} The new stricter generic check compares parameter |
I don't know if it is intended. But it seems very hard for users to understand.
Note in the #15104, it seems type parameter in generic type is checked co-variantly only when the type parameter is used in the parameter position of a callback (that is, a contravariant position in another contravariant position makes a cavariant position).
However, in the following example,
Done
is a plain function, not callback. SoA
is contravariantly checked. This might confuse old TS users.TypeScript Version: 2.4.1
Code
Expected behavior:
All compiles.
Actual behavior:
cloneAnimal
fails to compile.Argument of type '(d: Dog) => void' is not assignable to parameter of type 'Done'. Types of parameters 'd' and 'result' are incompatible. Type 'A' is not assignable to type 'Dog'. Type 'Animal' is not assignable to type 'Dog'. Property 'dogTag' is missing in type 'Animal'.
Related:
#16795
#16790
The text was updated successfully, but these errors were encountered: