வேற்றுமை ஒரு கூட்டு வகையின் உப-வகையாக்கம் அதன் பகுதிகளின் உப-வகையாக்கத்துடன் எவ்வாறு தொடர்புடையது என்பதை விவரிக்கிறது — அதாவது, Container<Sub> எப்போது Container<Super> க்கு ஒதுக்கப்பட முடியும்?
Dog ஐ Animal இன் உப-வகையாக விடுங்கள்.
வேற்றுமை ஒரு கூட்டு வகையின் உப-வகையாக்கம் அதன் பகுதிகளின் உப-வகையாக்கத்துடன் எவ்வாறு தொடர்புடையது என்பதை விவரிக்கிறது — அதாவது, Container<Sub> எப்போது Container<Super> க்கு ஒதுக்கப்பட முடியும்?
Dog ஐ Animal இன் உப-வகையாக விடுங்கள்.
let dogs: Dog[] = [];
let animals: Animal[] = dogs; // ✅ Dog[] is assignable to Animal[]
வழங்கல் வகைகள் மற்றும் வரிசைகள் இணைந்துள்ளன: Dog ⊆ Animal என்றால், Dog[] ⊆ Animal[]. Dog ஐ வழங்கும் செயல்பாடு 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
செயல்பாட்டு அளவுருக்கள் எதிர்நிலையாகவுள்ளன: Handler<Animal> Handler<Dog> க்கு ஒதுக்கப்பட முடியும், இது உপাদান உறவுக்கு எதிரெதிர். இது சரியாக உள்ளது — அனைத்து விலங்குகளையும் கையாளுவது நிச்சயமாக நாய்களை கையாளுகிறது.
// Method parameters in TS are bivariant by default (a known unsound convenience)
interface Comparer<T> { compare(a: T): void; }
TypeScript தனிமையான செயல்பாட்டு வகைகளை strictFunctionTypes இன் கீழ் மட்டுமே எதிர்நிலையாக சரிபார்க்கிறது; முறை அளவுருக்கள் ergonomics க்கான வேண்டுமென்றே இரு-வேறுபாடான ஆகும், இது தொழில்நுட்ப ரீதியாக உபயோகிக்க முடியாதது.
வேற்றுமை ஏன் சில ஒதுக்கங்கள் அனுமதிக்கப்படுகிறது அல்லது நிராகரிக்கப்படுகிறது என்பதை விளக்குகிறது — Dog[] ஏன் Animal[] க்கு பொருந்துகிறது ஆனால் ஒரு (d: Dog) => void கால்பேக் (a: Animal) => void க்கு எப்போதும் நிற்க முடியாது.
இதை புரிந்துகொள்வது உங்களை பொதுவான API கள் (எ.கா. படிக்க-மட்டுமே vs எழுதும் நிலைகள்) வடிவமைக்க உதவுகிறது மற்றும் செயல்பாடுகள் மற்றும் பொதுவானவற்றை சம்பந்தப்படுத்திய குழப்பமான "ஒதுக்கக்கூடியதல்ல" பிழைகளை புரிந்துகொள்ள உதவுகிறது.