A type predicate is a promise the compiler cannot check

A function returning x is Foo narrows the type at every call site, and the compiler takes the claim entirely on trust.

function isOrder(v: unknown): v is Order {
  return typeof v === 'object' && v !== null && 'total' in v;
}

// the compiler does NOT verify that the body checks everything
// Order declares six fields; this checks one. it compiles.

if (isOrder(data)) {
  data.customer.email;    // typed. possibly undefined at runtime.
}

A guard that under-checks is worse than no guard, because it moves the failure from a compile error to a runtime one while adding confidence. Writing them by hand for anything beyond a discriminator is where a schema validation library earns its place — the guard is then generated from the schema and cannot drift. Reviewing type predicates with the same care as a cast is the practical rule.