🔷 TypeScript Intermediate

What is covariance and contravariance in TypeScript?

Why Interviewers Ask This

This tests whether you can apply TypeScript knowledge to real-world scenarios. Interviewers are looking for clarity of thought and evidence that you've encountered this in production code.

Answer

Variance describes how subtyping relationships between complex types relate to subtyping of their component types. In TypeScript: Covariance means "subtype in, subtype out" — if Cat is a subtype of Animal, then Array<Cat> is a subtype of Array<Animal> (you can use a Cat array where an Animal array is expected). Most positions in TypeScript are covariant. Contravariance means the direction is reversed — if Cat extends Animal, a function (a: Animal) => void is a subtype of (c: Cat) => void. This is because a function that can handle any Animal can certainly handle a Cat, but not vice versa. TypeScript enforces contravariance for function parameters with "strictFunctionTypes": true. This matters for callbacks and event handlers — a more general callback is safely substitutable for a more specific one. Methods (unlike function properties) are bivariant in TypeScript for historical compatibility reasons.

Pro Tip

Before answering, structure your response: one-line definition → real-world analogy → concrete example from a project. This makes even complex TypeScript answers easy to follow.