Varijanca opisuje kako subtyping kompozitnog tipa odnos na subtyping njegovih dijelova — tj. kada je Container<Sub> dodjeljiv Container<Super>?
Neka Dog bude podtip od Animal.
let dogs: Dog[] = [];
let animals: Animal[] = dogs; // ✅ Dog[] is assignable to Animal[]
Povratne vrijednosti i nizi su kovarijantni: ako je Dog ⊆ Animal, tada je Dog[] ⊆ Animal[]. Funkcija koja vraća Dog može se koristiti gdje se očekuje vraćanje Animal.
type Handler<T> = (arg: T) => void;
let animalHandler: Handler<Animal> = (a) => {};
let dogHandler: Handler<Dog> = animalHandler; // ✅ (with strictFunctionTypes)
// a handler that accepts ANY Animal can safely handle a Dog
Parametri funkcije su kontravarijantni: Handler<Animal> je dodjeljiv Handler<Dog>, obrnuto od odnosa elemenata. Ovo je ispravno — sve što rukuje životinjama sigurno rukuje psima.
// Method parameters in TS are bivariant by default (a known unsound convenience)
interface Comparer<T> { compare(a: T): void; }
TypeScript provjerava samostalne tipove funkcija kontravarijantan samo pod strictFunctionTypes; parametri metode su namjerno bivarijantni radi ergonomije, što je tehnički neispravno.
Varijanca objašnjava zašto su određene dodjele dozvoljene ili odbijene — zašto Dog[] odgovara Animal[] ali callback (d: Dog) => void ne može uvijek biti zamjena za (a: Animal) => void.
Razumijevanje toga pomaže vam da dizajnirate generičke API-je (npr. samo čitanje u odnosu na pozicije pisanja) i desifrirate zbunjujuće greške "nije dodjeljivo" koje uključuju funkcije i generike.