Varianssi kuvaa, kuinka yhdistetyyn tyyppiin liittyvä aliasintyppi liittyy sen osien alitypointiin — eli milloin Container<Sub> on sijoitettavissa Container<Super> -kohteeseen?
Olkoon Dog tyypin Animal alitype.
let dogs: Dog[] = [];
let animals: Animal[] = dogs; // ✅ Dog[] is assignable to Animal[]
Palautustyypit ja taulukot ovat kovariantteja: jos Dog ⊆ Animal, niin Dog[] ⊆ Animal[]. Funktio, joka palauttaa Dog:n, voidaan käyttää, kun odotetaan funktiota, joka palauttaa Animal:n.
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
Funktion parametrit ovat kontravariitteja: Handler<Animal> voidaan sijoittaa Handler<Dog> -kohteeseen, mikä on vastakkainen alkioisuhteisuudelle. Tämä on pätevää — jotain, joka käsittelee kaikki eläimet, käsittelee varmasti koiria.
// Method parameters in TS are bivariant by default (a known unsound convenience)
interface Comparer<T> { compare(a: T): void; }
TypeScript tarkistaa itsenäiset funktiotyypit kontravariittisesti vain strictFunctionTypes -kohdalla; menetelmäparametrit ovat tarkoituksella bivariantteja ergonomian vuoksi, mikä on teknisesti turvaton.
Varianssi selittää, miksi tietyt sijoitukset sallitaan tai hylätään — miksi Dog[] sopii Animal[]:lle, mutta (d: Dog) => void -takaisinkutsu ei voi aina korvata (a: Animal) => void -kohtaa.
Kirjasto IT-haastattelukysymyksiä yksityiskohtaisine vastauksineen — Juniorista Senioriin.
Lahjoita