Covariance
- TypeScript course
- Advanced
- Lesson 13/57
- 4 min
Learn the covariance rule for functions.
What is covariance?
Covariance is the rule where the subtype relationship is preserved in the same direction. If Dog is a subtype of Animal, then () => Dog is treated as a subtype of () => Animal. You can assign a function returning Dog where a function returning Animal is expected.
class Animal { name = "animal"; }
class Dog extends Animal { bark() {} }
type AnimalMaker = () => Animal;
const makeDog: () => Dog = () => new Dog();
const maker: AnimalMaker = makeDog; // validCovariance in arrays
Arrays are covariant too: Dog[] is treated as a subtype of Animal[]. This follows from every element satisfying the Animal interface. The looseness also permits some unsound operations; for instance, assigning Dog[] where Animal[] is expected and then pushing another subtype into that array may not error at compile time.
const dogs: Dog[] = [new Dog(), new Dog()];
const animals: Animal[] = dogs; // valid: covariantPractice Demonstrate covariant function assignment
Define a Dog class extending Animal. Assign a () => Dog function to a () => Animal typed variable, and print the name property of the returned animal via console.log.
Starter code
class Animal {
name = "animal";
}
// Dog sınıfını Animal'dan türet
// köpek üreten fonksiyonu tanımla
// covariant atama yapıp sonucu yazdırSample solution
class Animal {
name = "animal";
}
class Dog extends Animal {}
const makeDog: () => Dog = () => new Dog();
const makeAnimal: () => Animal = makeDog;
const a = makeAnimal();
console.log(a.name);Expected output
animal
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Which of the following assignments is valid due to covariance?
- const a: Dog = new Animal();
- const a: () => Animal = () => new Dog(); Correct answer
- const a: () => Dog = () => new Animal();
- const a: Dog[] = [new Animal()];
Explanation: Covariance works in the same direction for return types; a function returning Dog is assignable where Animal is expected.
2 Covariant return type
class Animal {}
class Cat extends Animal {}
const makeCat: () => Cat = () => new Cat();
const makeAnimal: () => Animal = ____;
class Animal {}
class Cat extends Animal {}
const makeCat: () => Cat = () => new Cat();
const makeAnimal: () => Animal = makeCat;
Explanation: makeCat returns Cat and Cat is an Animal, so via covariance it is assignable to a () => Animal expectation.
3 Covariance parts
| Term | Meaning |
|---|---|
Dog alt tür, Animal üst tür |
subtype relation |
() => Dog |
assignable to Animal-returning expectation |
Dog[] |
counted as subtype of Animal[] |
Dönüş türü |
Covariance area |