CodeBlanks Logo Icon CodeBlanks

Summary - Variance

Write a program comparing variance rules.

Summary - Variance

Variance rules describe how a subtype relationship propagates to function types. Covariance keeps the relationship in the same direction (return type, arrays). Contravariance reverses it (parameter type, under strictFunctionTypes). Bivariance accepts both directions (method shorthand or strict off).

class Animal {}
class Dog extends Animal {}

// Covariance (return type):
const a: () => Animal = () => new Dog();

// Contravariance (parameter, under strict):
const b: (d: Dog) => void = (x: Animal) => {};

// Bivariance (method shorthand):
interface Kennel { keep(d: Dog): void; }
const k: Kennel = { keep(x: Animal) {} };

Practice Show all three rules in one program

Define a Dog class extending Animal. Show three things: (1) Covariance: assign a () => Dog function to a () => Animal type and print the name of the returned object. (2) Contravariance: assign a (a: Animal) => void function to a (d: Dog) => void type. (3) Bivariance: write a Kennel interface with a keep(d: Dog): void method and implement it as keep(a: Animal) {}. Print the labels "covariance", "contravariance", "bivariance" via console.log before each section.

Starter code

index.ts
class Animal {
  name = "animal";
}

// Dog sınıfını tanımla

// 1) Covariance: () => Dog -> () => Animal

// 2) Contravariance: (a: Animal) => void -> (d: Dog) => void

// 3) Bivariance: Kennel interface ve implementation

Sample solution

index.ts
class Animal {
  name = "animal";
}

class Dog extends Animal {}

console.log("covariance");
const makeAnimal: () => Animal = () => new Dog();
console.log(makeAnimal().name);

console.log("contravariance");
const dogHandler: (d: Dog) => void = (a: Animal) => {};
dogHandler(new Dog());

console.log("bivariance");
interface Kennel {
  keep(d: Dog): void;
}
const k: Kennel = {
  keep(a: Animal) {}
};
k.keep(new Dog());

Expected output

covariance
animal
contravariance
bivariance

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 How is the return type checked in a function type (with strictFunctionTypes on)?

  • Invariant
  • Contravariant
  • Covariant Correct answer
  • Bivariant

Explanation: The return type is always checked covariantly; a function returning a subtype is assignable where a supertype return is expected.

2 Which type for a contravariant parameter

Question
class Animal {}
class Dog extends Animal {}

// Contravariance örneği: h, Dog beklerken implementation Animal kabul eder
const h: (d: Dog) => void = (x: ____) => {};
Answer
class Animal {}
class Dog extends Animal {}

// Contravariance örneği: h, Dog beklerken implementation Animal kabul eder
const h: (d: Dog) => void = (x: Animal) => {};

Explanation: For contravariance the parameter must be a supertype of the target's parameter; Animal is the supertype of Dog, so it is correct.

3 Variance rules matching

Term Meaning
Dönüş türü Covariance
Parametre (strict altında) Contravariance
Method shorthand Bivariance
Dog döndüren fonksiyon assignable to Animal-returning expectation

All lessons in Advanced