Skip to content
webtype.orgVariance annotations

    ↑↓ move · ⏎ open · esc close

    Constructs

    Variance annotations

    `in` and `out` state how a generic behaves when its parameter changes — which TypeScript otherwise works out for itself.

    What it is

    Added in 4.7, and unusual in that they change nothing about what is legal: TypeScript already infers variance structurally. What they buy is speed and intent — the compiler can skip the structural comparison, and a reader is told outright whether a `Box<string>` may stand in for a `Box<string | number>`. `out` means the parameter is produced, `in` that it is consumed, `in out` both.

    Examples

    • Producer<string> extends Producer<string | number> ? true : false
      true

      Covariant: something that produces strings will do wherever something producing strings-or-numbers is wanted.

    • Consumer<string | number> extends Consumer<string> ? true : false
      true

      Contravariant, and the direction reverses: something that accepts more will do wherever something accepting less is wanted.

    • Consumer<string> extends Consumer<string | number> ? true : false
      false

      And the other way round it fails, which is the whole point of the annotation being there.

    Each resolved type above was printed by TypeScript 5.9.3, not written by hand.

    What it does not do

    • They do not make anything legal that was not. Annotate wrongly and the compiler rejects the annotation, not the usage — it checks your claim against the structure.
    • They are not needed on most types. Reach for them on large recursive generics where variance inference is measurably slow, not as a matter of style.

    Takeaway

    Variance is the rule that decides when one generic can stand in for another. You have been relying on it since your first array; these keywords only let you say it out loud.