Variance njelasake carane subtyping saka composite type ana hubungane karo subtyping saka bagian-bagiane — yaiku kapan Container<Sub> bisa dipenak kanggo Container<Super>?
Kapacukke Dog minangka subtype saka Animal.
let dogs: Dog[] = [];
let animals: Animal[] = dogs; // ✅ Dog[] is assignable to Animal[]
Return types lan arrays iku covariant: menawa Dog ⊆ Animal, banjur Dog[] ⊆ Animal[]. Fungsi sing bali Dog bisa digunakake yen pengguna ngarepaken sing bali 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
Parameter parameters iku contravariant: Handler<Animal> bisa dipenak kanggo Handler<Dog>, kebalikan saka hubungan elemen. Iki sehat — bab sing nangani kabeh kewan mesthi nangani asu.
// Method parameters in TS are bivariant by default (a known unsound convenience)
interface Comparer<T> { compare(a: T): void; }
TypeScript mriksa standalone function types kanthi cara contravariant mung ana strictFunctionTypes; parameter metode kanthi sengaja bivariant kanggo ergonomics, kang technically ora sehat.
Variance njelasake ngapa penugasan tartamtu diidini utawa ditolak — ngapa Dog[] cocok Animal[] nanging callback (d: Dog) => void ora bisa tansah ngganti (a: Animal) => void.
Ngerti iku membantu kowe ndesain generic APIs (contone read-only vs write positions) lan maca confusing "not assignable" errors sing ana hubungane karo fungsi lan generics.