TypeScript
Bivariance and strict
Learn the difference between bivariance and strictFunctionTypes.
What is bivariance?
Bivariance is the loose rule where parameter types are accepted both covariantly and contravariantly. When strictFunctionTypes is off, all function parameters are checked bivariantly. This permits some unsound assignments but is kept for backward compatibility.
class Animal {}
class Dog extends Animal {}
interface Kennel {
keep(d: Dog): void; // method shorthand
}
const k: Kennel = { keep(a: Animal) {} }; // bivariant: valid
Method vs function-typed property
The same logical function, written as a method shorthand in an interface, is checked bivariantly; written as a function-typed property (with strictFunctionTypes on) it is checked contravariantly. Event-handler style code typically uses method shorthand; that looseness is needed when working with DOM event types.
interface A {
method(p: Dog): void; // bivariant (always)
property: (p: Dog) => void; // contravariant (under strict)
}
Exercise Demonstrate bivariance with a method
Define a Dog class extending Animal. Write a Kennel interface containing a keep(d: Dog): void method. Create a Kennel object whose keep method has the signature (a: Animal) => {}; this is valid thanks to bivariance. Finally call k.keep(new Dog()) and print console.log("ok").
Show example solution
class Animal {}
class Dog extends Animal {}
interface Kennel {
keep(d: Dog): void;
}
const k: Kennel = {
keep(a: Animal) {}
};
k.keep(new Dog());
console.log("ok");
Test yourself
-
Which declaration is checked bivariantly even with strictFunctionTypes on?
- Function-typed property: prop: () => void
- Function declared with method shorthand inside an interface
- Const variable written as an arrow function
- Function type declared with a type alias () => void
Show answer
Function declared with method shorthand inside an interface — Method shorthand (name(p: T): R) is always checked bivariantly; strictFunctionTypes affects only function-typed properties.
-
Bivariance method declaration
class Animal {}
class Dog extends Animal {}
interface Kennel {
// bivariant method:
keep(d: Dog)____;
}
Show answer
class Animal {}
class Dog extends Animal {}
interface Kennel {
// bivariant method:
keep(d: Dog): void;
}
-
Bivariance parts
- strictFunctionTypes kapalı
- all parameters bivariant
- Method shorthand
- always bivariant
- Function-typed property
- contravariant under strict
- Bivariance
- both covariant and contravariant
Next lesson: Summary - Variance