- 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
// 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).