- Sound mode S-07, pre-alpha
- Design record 0007, Accepted
TSR0702
Type predicate '{0} is {1}' is not proved: when it returns false, '{0}' can still be '{1}'.
A type guard returns false for some values that are T, so callers would narrow them away wrongly. Make the false side exact 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
Callers narrow a parameter to "not T" when a type predicate returns false. In a sound file, wherever the guard returns false, the parameter's flow type must fit that narrowed type. A guard like x === "a" for x is string returns false for other strings, which callers would then treat as numbers.
Example
// When this returns false, x can still be a string, but callers would narrow it to number.
function isString(x: string | number): x is string { // @expect TSR0702
return x === "a";
}
function measure(v: string | number): number {
return isString(v) ? v.length : v;
}
export const n: number = measure("b");
How to fix
- Make the check match the predicate exactly:
typeof x === "string"forx is string. - Or narrow the predicate to what the body checks (
x is "a").
Sound mode is defined in design record 0007 (accepted 2026-10-15).