EN
TypeScript - covariance concept
10
points
In this short article, we would like to explain covariance concept in TypeScript.
Main concept:
Main definition:
GenericType<...>types are covariant if it preserves the ordering of types (≤), which orders types from more specific to more abstract, so:if
BaseType ≤ SubType, thenGenericType<BaseType> ≤ GenericType<SubType>.
In simple worlds:
Covariance alows to cast, without any restrictions, some specific types to more abstract types when composed types are used.
Practical examples
Example 1:
class Animal {
public name: string;
public constructor(name: string) {
this.name = name;
}
}
class Cat extends Animal {
public mousehunter: boolean;
public constructor(name: string, mousehunter: boolean) {
super(name);
this.mousehunter = mousehunter;
}
}
const createTom = async (): Promise<Cat> => { return new Cat('Tom', true); };
const createAnimal = async (): Promise<Animal> => { return await createTom(); };
// ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
// | |
// According to covariance concept we can cast Promise<Cat> to Promise<Animal>.
// ...
Example 2:
class Animal {
public name: string;
public constructor(name: string) {
this.name = name;
}
}
class Cat extends Animal {
public mousehunter: boolean;
public constructor(name: string, mousehunter: boolean) {
super(name);
this.mousehunter = mousehunter;
}
}
const cats: Array<Cat> = [
new Cat('Tom', true),
new Cat('Simba', false),
new Cat('Nala', false)
];
const animals: Array<Animal> = cats;
// ^^^^^^^^^^^^^ ^^^^
// | |
// According to covariance concept we can cast Array<Cat> to Array<Animal>.
// ...