Skip to content

Type guards on variable break refinements on its properties #18840

Closed
@ivogabe

Description

@ivogabe

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.

Metadata

Metadata

Assignees

Labels

FixedA PR has been merged for this issueIn DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions