Variancia azt írja le, hogy az összetett típus altípusa hogyan viszonyul részei alípusaihoz — vagyis amikor a Container<Sub> hozzárendelhető a Container<Super> típushoz?
Legyen Dog az Animal altípusa.
Variancia azt írja le, hogy az összetett típus altípusa hogyan viszonyul részei alípusaihoz — vagyis amikor a Container<Sub> hozzárendelhető a Container<Super> típushoz?
Legyen Dog az Animal altípusa.
let dogs: Dog[] = [];
let animals: Animal[] = dogs; // ✅ Dog[] is assignable to Animal[]
A visszatérési típusok és tömbök kovariaciánisak: ha Dog ⊆ Animal, akkor Dog[] ⊆ Animal[]. Egy Dog típust visszaadó függvény használható ott, ahol Animal visszaadása várható.
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
A függvény paraméterei kontravariaciánisak: a Handler<Animal> hozzárendelhető a Handler<Dog> típushoz, ami az elem-viszony fordítottja. Ez helyes — amini minden állattal képes bánni, az bizonyosan képes kutyákkal is bánni.
// Method parameters in TS are bivariant by default (a known unsound convenience)
interface Comparer<T> { compare(a: T): void; }
A TypeScript az önálló függvénytípusokat csak a strictFunctionTypes alatt vizsgálja meg kontravariaciánisan; a metódus-paraméterei szándékosan bivariaciánisak az ergonómia miatt, ami technikailag nem biztonságos.
A variancia elmagyarázza, miért engedélyeztek vagy elutasítanak bizonyos hozzárendeléseket — miért illeszkedik a Dog[] az Animal[] típushoz, de a (d: Dog) => void callback nem tud mindig helyettesíteni egy (a: Animal) => void típust.
Annak megértése segít generikus API-ket tervezni (pl. csak olvasható vs. írási pozíciók) és dekódolni a zavaró "nem hozzárendelhető" hibákat, amelyek függvényeket és generikusokat tartalmaznak.