ReviseAlgo Logo

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 type F is Covariant if F is assignable to F. Readonly collections and function return types are covariant.

2. Contravariance (Input Positions — Consumer)

A generic type F 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 type F 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 ModeSubtyping RelationshipTypical LocationAnnotation Keyword
    CovariantF \subseteq FReturn types, Readonly gettersout T
    ContravariantF \subseteq FParameter input positionsin T
    | Invariant | Neither direction allowed | Mutable properties & read/write methods | in out T |