Bivariance and strict
- TypeScript course
- Advanced
- Lesson 15/57
- 4 min
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: validMethod 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)
}Practice 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").
Starter code
class Animal {}
// Dog sınıfını Animal'dan türet
// Kennel interface'ini method shorthand ile tanımla
// Kennel nesnesini Animal kabul eden implementation'ıyla oluştur
// keep'i bir Dog ile çağır ve "ok" yazdırSample 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");Expected output
ok
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Which declaration is checked bivariantly even with strictFunctionTypes on?
- Function-typed property: prop: () => void
- Function declared with method shorthand inside an interface Correct answer
- Const variable written as an arrow function
- Function type declared with a type alias () => void
Explanation: Method shorthand (name(p: T): R) is always checked bivariantly; strictFunctionTypes affects only function-typed properties.
2 Bivariance method declaration
class Animal {}
class Dog extends Animal {}
interface Kennel {
// bivariant method:
keep(d: Dog)____;
}
class Animal {}
class Dog extends Animal {}
interface Kennel {
// bivariant method:
keep(d: Dog): void;
}
Explanation: Method shorthand keep(d: Dog): void is always checked bivariantly; even with strictFunctionTypes on, parameter contravariance is relaxed.
3 Bivariance parts
| Term | Meaning |
|---|---|
strictFunctionTypes kapalı |
all parameters bivariant |
Method shorthand |
always bivariant |
Function-typed property |
contravariant under strict |
Bivariance |
both covariant and contravariant |