The error disappeared. Can you trust the data?

An API returns { "seats": "many" }, but the application expects a seat count. An any annotation or assertion quiets the editor while leaving the runtime problem intact. A passing type check cannot establish the shape of external input.

Predict what asserting { seats: number } does to a string value. It does not convert it. This lesson checks a value at the boundary, then preserves the information established there.

外部数据先验证再收窄 / Treat external data as unknown and validate it before trusting its type.外部数据先验证再收窄 / Treat external data as unknown and validate it before trusting its type.
Treat external data as unknown and validate it before trusting its type.

Narrow unknown with actual checks

unknown means the value has not been established yet. Check existence, shape and field constraints before reading properties or calculating. This example accepts only a nonnegative integer count and explicitly rejects other inputs.

ts
function readSeats(value: unknown): number {
  if (typeof value !== "object" || value === null) {
    throw new Error("Expected an object");
  }
  if (!("seats" in value)) {
    throw new Error("Missing seats");
  }
  const seats = value.seats;
  if (typeof seats !== "number" ||
      !Number.isInteger(seats) || seats < 0) {
    throw new Error("Invalid seat count");
  }
  return seats;
}

These checks establish only the conditions they examine. They say nothing about account permissions or changing inventory, and do not repair input. A larger response may need another runtime validation approach with an equally explicit acceptance policy.

Use a generic to retain a relationship

An identity function can accept text or numbers but lose the particular input type if its return annotation is a union. A generic expresses that the output keeps the input's type without requiring a separate implementation for each type.

echoWide(12) 返回较宽的联合类型;泛型 echo(12) 保留类型 12。 / Compare echoWide(12), returning string | number, with generic echo(12), retaining type 12.echoWide(12) 返回较宽的联合类型;泛型 echo(12) 保留类型 12。 / Compare echoWide(12), returning string | number, with generic echo(12), retaining type 12.
Compare echoWide(12), returning string | number, with generic echo(12), retaining type 12.
ts
function echoWide(value: string | number): string | number {
  return value;
}
function echo<T>(value: T): T {
  return value;
}
const wide = echoWide(12); // string | number
const precise = echo(12); // 12

If you don't know generics, I promise you'll understand them by the end of this thread.

— Matt Pocock

Read the error as three plain statements

Identify the expected type, the actual type and the layer where they disagree. Then reduce the case. Passing wide to a number-only function fails because its declared type still includes text: the return declaration lost the relationship.

Read a type errorA workflow diagram generated by Archify.Read a type errorType errorExpected type?Actual type?Mismatch layer?Minimal reproductionRoot causeFrom error to causeError translators assist; they cannot establishcorrectness.
Translate a type error into expectations, actual values and the mismatch.

ts-reset changes declarations

In the collected version, ts-reset adjusts selected built-in declarations, including treating JSON parsing results as unknown so callers must check them. It provides no runtime input validation. Assess project compatibility and the effect of global declarations before adoption.

TRY IT

Predict the boundary before running it

  • Task: Predict readSeats for { seats: 3 }, { seats: "3" } and null. Run the cases and compare.
  • Explain why echoWide's result cannot immediately be used as number, and which layer you would change.
Suggested approach

Only the first input returns 3; the others throw. echoWide's declaration permits text. If the contract is to return the input unchanged, use a generic to retain that relationship, or narrow at the caller. An assertion alone establishes no numeric condition.

Done means you can explain and demonstrate the boundary

Explain what an assertion has not validated. Predict and run valid and invalid inputs, then describe a type mismatch in ordinary language. Identify the relationship a generic preserves. Continue with practical type tools.

Quick reference

01

unknown

Check the value before relying on its shape.

02

Generics

Preserve a type relationship between inputs and outputs.

03

Errors

Identify expected, actual and location; reduce the case before fixing it.

Sources

Unofficial, non-commercial study notes, with no affiliation with or endorsement by Matt Pocock. Quoted works belong to their authors; MIT reuse carries separate copyright and licence notices.