Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support type guards on property access expression #3812

Closed
tinganho opened this issue Jul 10, 2015 · 9 comments
Closed

Support type guards on property access expression #3812

tinganho opened this issue Jul 10, 2015 · 9 comments
Assignees
Labels
Committed The team has roadmapped this issue Fixed A PR has been merged for this issue Suggestion An idea for TypeScript

Comments

@tinganho
Copy link
Contributor

I just found out that property access expressions doesn't work on type predicate functions and instanceof type guards.

class A {
    propA: number;
}

class B {
    propB: number;
}
class C {
    propC: A;
}

declare function isA(p1: any): p1 is D;

interface D {
    a: A | B
    b: A | C;
}

let d: D;
if (isA(d.b)) {
    d.b.propA; //error
}

function foo(d: D) {
    if (d.b instanceof A) {
        d.b.propA // error
    }
}

I'm not sure if there is an easy fix on this problem. We are provided just a symbol when narrowing. That symbol represent the left most expression and then we walk up the if statement. There is no easy way of controlling symbol by symbol on each namespace in a property access expression in the if-statement-body. Because there is no info about the property access expression provided in getTypeOfSymbolAtLocation(symbol: Symbol, node: Node).

I also found that type assertion expressions are also not working in type predicate functions. But I will land a fix on that.

if (isA(<A>union)) {
    a = union;
}
if (isA(union as A)) {
    a = union;
}
@danquirk
Copy link
Member

I believe I ran into similar cases when first playing with #1260. This is by design (4.20):
Note that type guards affect types of variables and parameters only and have no effect on members of objects such as properties
so I will edit the title to reflect the suggestion a little more clearly.

@danquirk danquirk added Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. labels Jul 10, 2015
@danquirk danquirk changed the title Property access expression in type guards doesn't work Support type guards on property access expression Jul 10, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Jul 10, 2015

is not this a duplicate of #1260?

@danquirk
Copy link
Member

Upon reflection probably yes unless there's something unique about the more recent changes to type guards supporting basic property access but not instanceof/user defined type guards

@mhegazy
Copy link
Contributor

mhegazy commented Jul 10, 2015

instance of and use type guards are just two checks, if we allow narrowing by property access, we will need to add it every where, typeof, instanceof, type guards ..etc..

@danquirk
Copy link
Member

Yeah, that's what I figured, will just close this then.

@danquirk danquirk added Duplicate An existing issue was already created and removed Suggestion An idea for TypeScript Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. labels Jul 10, 2015
@RyanCavanaugh
Copy link
Member

I don't think #1260 and this are really the same thing

@Joncom
Copy link

Joncom commented Feb 29, 2016

The following example demonstrates the problem, which still exists in 1.8.2:

interface Foo {
    myProperty: (boolean | string)
}

var foo: Foo = {
    myProperty: "Hello World"
};

var p = foo.myProperty;
if (typeof p === "string") {
    // This works fine!
    console.log(p.length); // Prints `11`
}

if (typeof foo.myProperty === "string") {
    // This line produces the following compilation error:
    // "Property 'length' does not exist on type 'boolean | string'."
    console.log(foo.myProperty.length);
}

@RyanCavanaugh RyanCavanaugh added Committed The team has roadmapped this issue and removed In Discussion Not yet reached consensus labels Mar 8, 2016
@RyanCavanaugh
Copy link
Member

This will be going in as part of the non-nullable type work

@mhegazy mhegazy added this to the TypeScript 2.0 milestone Mar 8, 2016
@ahejlsberg
Copy link
Member

Closed in #7140.

@mhegazy mhegazy added the Fixed A PR has been merged for this issue label Apr 14, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Committed The team has roadmapped this issue Fixed A PR has been merged for this issue Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants