LLearnCode
Academy/typescript/Production TypeScript

advanced · 24 minute study

A callback must accept everything its caller can send

Function compatibility errors often reveal a real mismatch between who chooses an input and who promises to handle it.

Loading progressEvidence grows with practice
Useful preparation · 1 prerequisite

Use this as a map, not a lock. If these ideas are familiar, continue.

First, build a mental model

The caller owns the choice of input. A callback cannot safely narrow that promise to a smaller set of values just because its implementation is specialized.

  1. Under strictFunctionTypes, function-typed parameters are checked conservatively.
  2. If a caller may pass string or number, a callback handling only string is too narrow.
  3. TypeScript has deliberate compatibility exceptions, including method parameter bivariance; do not confuse those with runtime guarantees.
  4. Overloads describe supported relationships; a union is simpler when every input shares the same output relationship.
Read the codetypescript · educational example
type Consumer = (value: string | number) => string;
const textOnly = (value: string) => value.toUpperCase();
// const unsafe: Consumer = textOnly;
const safe: Consumer = value =>
  typeof value === 'string' ? value.toUpperCase() : String(value);
  1. Caller promise

    Consumer's caller may provide a number.

  2. Narrow implementation

    textOnly would call toUpperCase on that number.

  3. Repair

    safe handles both possible input kinds.

Production thinking

Take this beyond the example.

Favor explicit callback types at module boundaries and test the widest allowed inputs. A cast is not a substitute for a compatible implementation.

Sources and further reading

Your evidence

unseen is a local learning signal, not a credential or proof of production competence.

Explain the mental model, then explicitly acknowledge it. Opening a page is not evidence.

Supported retries can complete this lesson. Independent evidence and delayed review determine the skill stage.

Next lesson · Make failure part of the API contract →