• Sound mode S-07, pre-alpha
  • Design record 0007, Accepted

TSR0701

Type predicate '{0} is {1}' is not proved: when it returns true, '{0}' can be '{2}'.

A type guard ('x is T') returns true for values that aren't T. Make the checks in its body prove T, or use is<T>().

Rule S-07: Type guards must be proved (level: sound). Reported by ts-r-check and ts-r-lsp in files that opt in to sound mode. See Sound mode.

What it means

A user-defined type predicate on a function with a body in a sound file must be proved by its body: wherever it returns true, the checker's flow type of the parameter must be assignable to the predicate type. It's reported at the predicate in the signature. Predicates without a body (interfaces, overloads, .d.ts) are trusted.

Example

Spec case from design record 0007 (checked by the record's case harness, not by this site's build)
// A generic guard that always says yes.
function isPresent<T>(x: T | null): x is T { // @expect TSR0701
  return true;
}
function orEmpty(v: string | null): string {
  return isPresent(v) ? v : "";
}
export const s: string = orEmpty(null);

How to fix

  • Check enough in the body that the true side really is T (typeof, instanceof, discriminants).
  • Generate the guard from the type: return is<T>(x) with @ts-r.dev/guard.
  • For a guard that checks a few fields of a larger type, validate the whole type instead.

Sound mode is defined in design record 0007 (accepted 2026-10-15).