Skip to the solution
HardFrontend12 min read

What are covariance and contravariance?

319 views

The problem

Question presented to candidate: "If a Dog is assignable to an Animal, is a Dog[] assignable to an Animal[]? Is a (d: Dog) => void assignable to an (a: Animal) => void? Explain covariance and contravariance, and where TypeScript is deliberately unsound."

What a strong answer should cover:

  • Variance describes how a subtype relation between Dog and Animal carries over to a type built from them, such as Box<Dog> and Box<Animal>: same direction (covariant), reversed (contravariant), neither (invariant), or both (bivariant)
  • Outputs (return types, read-only properties) are covariant; inputs (parameters) are contravariant, because a function that accepts any Animal can safely be used where only Dogs will be passed
  • strictFunctionTypes (TypeScript 2.6, part of --strict) checks function-type parameters contravariantly, but parameters declared with method syntax stay bivariant on purpose
  • Mutable arrays are treated as covariant, which is unsound: you can push a Cat into a Dog[] through an Animal[] alias; readonly arrays are covariant and safe
  • A generic type that both reads and writes T is invariant; TypeScript measures variance from the structure, and in / out annotations (TypeScript 4.7) declare and check it

Clarifying questions expected:

  • Is strictFunctionTypes (or strict) on in this codebase?
  • Are the callbacks declared with method syntax or as function-typed properties?

Code / implementation expected: Yes β€” assign a Dog-only callback where an Animal callback is expected, show the compile error, and show the array hole at run time.

  • variance

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

12 min read Β· 11 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

TypeScriptCovariant returns, contravariant parameters and the array hole
TypeScriptMethod bivariance, measured variance and in / out annotations

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 78 of 81 in TypeScript

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

What is `isolatedDeclarations` and how does it enable single-file transpilation for declaration emit?

Continue