Generics
Variance — Covariance & Contravariance
Master Variance in TypeScript, Covariance, Contravariance, Invariance, Bivariance, in/out generic annotations, and type assignability rules.
Last Updated: July 29, 2026
•
10 min read
Variance refers to how subtyping between complex generic types (e.g. List vs List) relates to subtyping between their underlying component types (Dog vs Animal).
1. The Subtyping Hierarchy Baseline
Assume Dog is a subtype of Animal (Dog extends Animal):
2. Four Types of Variance
1. Covariance (Output Positions — Producer)
A generic typeF is Covariant if F is assignable to F. Readonly collections and function return types are covariant.2. Contravariance (Input Positions — Consumer)
A generic typeF is Contravariant if F is assignable to F (the direction flips!). Function parameter types are contravariant.3. Invariance (Both Input and Output Positions)
A generic typeF is Invariant if F and F are NOT assignable to each other in either direction. Mutable data structures (Container) are invariant.
4. Bivariance
F and F are mutually assignable in both directions (historical TypeScript method signature checking behavior under non-strict function types).
3. Explicit Variance Annotations (in / out Keywords)
TypeScript 4.7 introduced explicit variance annotations on generic parameters to speed up compiler type-checking:
out T: Explicitly marks T as Covariant (produced as output only).in T: Explicitly marks T as Contravariant (consumed as input only).in out T: Explicitly marks T as Invariant (both input and output).4. Interactive Code Playground
Test covariance and contravariance below:
5. Summary Table
| Variance Mode | Subtyping Relationship | Typical Location | Annotation Keyword |
|---|---|---|---|
| Covariant | F \subseteq F | Return types, Readonly getters | out T |
| Contravariant | F \subseteq F | Parameter input positions | in T |
in out T |