TypeScript Version: 2.5.2 & nightly (2.6.0-dev.20170929)
Code
interface A { type: "a", foo: string };
interface B { type: "b", foo: string | number };
function f(x: A | B) {
if (typeof x.foo === "number") return;
// x.foo: string
let y = x.type === "a" ? 1 : 2;
x.foo.substring(1, 2);
}
Expected behavior:
Given that the first line of the body of f checks whether x.foo is a string, the last line of the body should not cause an error.
Actual behavior:
The compiler shows an error on the last line of the body of f, since the type of x.foo is (wrongly) resolved to string | number instead of string. The type guard on the first line of f is not considered.
file.ts(11,8): error TS2339: Property 'substring' does not exist on type 'string | number'.
I think that this happens because the compiler only searches for property type guards (on x.foo in this case) until the last refinement on the related variable (in this case x). It would be better if it would search until the last assignment, as type guards on x should not break any refinement on properties.
Note that the correct behavior can be found when commenting the line that declares y.
TypeScript Version: 2.5.2 & nightly (2.6.0-dev.20170929)
Code
Expected behavior:
Given that the first line of the body of
fchecks whetherx.foois a string, the last line of the body should not cause an error.Actual behavior:
The compiler shows an error on the last line of the body of
f, since the type ofx.foois (wrongly) resolved tostring | numberinstead ofstring. The type guard on the first line offis not considered.I think that this happens because the compiler only searches for property type guards (on
x.fooin this case) until the last refinement on the related variable (in this casex). It would be better if it would search until the last assignment, as type guards onxshould not break any refinement on properties.Note that the correct behavior can be found when commenting the line that declares
y.