Skip to content

Readonly on field causes control flow analysis to work strangely #13247

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

Closed
EdAyers opened this issue Jan 2, 2017 · 4 comments
Closed

Readonly on field causes control flow analysis to work strangely #13247

EdAyers opened this issue Jan 2, 2017 · 4 comments

Comments

@EdAyers
Copy link

EdAyers commented Jan 2, 2017

TypeScript Version: 2.1.4

Code
Attempted to compile this on the typescript playground and with tsc 2.1.4 on my mac.
This could just be my misunderstanding of how the readonly keyword works.

type whatever = any 
//problems regardless of what we set `whatever` to

class Fish {
    readonly name: whatever; //fish never change their names
    constructor(name: whatever) {
        this.name = name;
    }
}
class Bird {
    name: whatever;
    constructor(name: whatever) {
        this.name = name;
    }
}

function getName(x: Fish | Bird) : whatever {
    if (x instanceof Fish) {
        return x.name;
    }
    else if (x instanceof Bird) {
        return x.name;
    }
}

Expected behavior:

x in the first if block has type Fish
x in the second block has type Bird

Actual behavior:

x in the first block has type Fish | Bird
x in the second block has type never

error TS2339: Property 'name' does not exist on type 'never'.

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Jan 2, 2017

See #202, #11965, and many others. Actually, it seems things have changed.

@EdAyers
Copy link
Author

EdAyers commented Jan 2, 2017

If typescript was doing a structural check, Birds are assignable as Fish. But if I remove the readonly keyword the error goes away and control flow works as expected. If I add more fields to Fish, then Bird is no longer assignable to Fish and the error goes away too. I don't understand why adding readonly would change how assignability works.

@xLama
Copy link

xLama commented Jan 3, 2017

Could it be related to this?

class FileSystemObject {
    isFile(): this is MyFile { return this instanceof MyFile; }
    isDirectory(): this is Directory { return this instanceof Directory; }
}
class MyFile extends FileSystemObject {
    name; 
}
class Directory extends FileSystemObject {}


let fso: FileSystemObject;
if (fso.isFile()) {
    fso; // fso is MyFile
}
else if (fso.isDirectory()) { // It works fine but if we remove name from MyFile fso become never
    fso; // fso is Directory
}

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label May 24, 2017
@RyanCavanaugh
Copy link
Member

This works as expected now

@RyanCavanaugh RyanCavanaugh removed the Needs Investigation This issue needs a team member to investigate its status. label Sep 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants