Ubadilikaji unaeleza jinsi uwiano wa aina ya kiwanja unavyohusiana na uwiano wa sehemu zake — yaani, je Container<Sub> inaweza kugawwa kwa Container<Super> lini?
Biaraka Dog kuwa aina ndogo ya Animal.
let dogs: Dog[] = [];
let animals: Animal[] = dogs; // ✅ Dog[] is assignable to Animal[]
Aina za kurudi na safu ni nyingi: ikiwa Dog ⊆ Animal, kisha Dog[] ⊆ Animal[]. Chaguo la kukokotoa linalorudisha Dog linaweza kutumiwa ambapo linalorudi Animal limetarajiwa.
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
Vigezo vya chaguo la kukokotoa vina kinyume: Handler<Animal> inaweza kugawwa kwa Handler<Dog>, kinyume cha uhusiano wa kipengele. Hii ni nzuri — kitu kinachoshughulikia wanyama wote hakika kinashughulikia mbwa.
// Method parameters in TS are bivariant by default (a known unsound convenience)
interface Comparer<T> { compare(a: T): void; }
TypeScript inakagua aina za chaguo la kukokotoa lengwa kwa kinyume tu chini ya strictFunctionTypes; vigezo vya chaguo ni kwa makusudi vya pande zote kwa kazi, ambayo ni kwa utata sio nzuri.
Ubadilikaji unashoowa kwa nini matoleo mahususi yameruhusiwa au yakataliwa — kwa nini Dog[] inafaa Animal[] lakini (d: Dog) => void callback haikusi kusimama ili (a: Animal) => void.
Kuielewa husaidia utayarisha API za jeneriki (mfano safu iliyolindwa kutoka kwa maeneo ya kuandika) na kusimbua hitilafu zinazosumbua "sio inayoweza kugawwa" zinazohusisha chaguo na jeneriki.