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

type guard doesn't seem to work on interfaces #1957

Closed
donnut opened this issue Feb 6, 2015 · 9 comments
Closed

type guard doesn't seem to work on interfaces #1957

donnut opened this issue Feb 6, 2015 · 9 comments
Labels
Duplicate An existing issue was already created

Comments

@donnut
Copy link

donnut commented Feb 6, 2015

The type guard instanceof Array does not seem to recognize the type of the interface IMessage.

interface IMessage {
    name: string;
}

function itemFn(pipIn: IMessage[]) {
    return pipIn;
}

function baseFn(pipIn: IMessage) {
    return [pipIn];
}

function main(pipIn: IMessage|IMessage[]) {
    if (pipIn instanceof Array) {
        return itemFn(pipIn);
    } else {
        return baseFn(pipIn);
    }
}

The compiler outputs the error message:

unions6.ts(19,23): error TS2345: Argument of type 'IMessage | IMessage[]' is not assignable to parameter of type 'IMessage'.
  Type 'IMessage[]' is not assignable to type 'IMessage'.

I'm using master of today.

Thanks

@danquirk
Copy link
Member

danquirk commented Feb 6, 2015

This is working as intended according to the latest spec.

From section 4.20 Type Guards:

  • A type guard of the form x instanceof C, where x is not of type Any, C is of a subtype of the global type 'Function', and C has a property named 'prototype'
    • when true, narrows the type of x to the type of the 'prototype' property in C provided it is a subtype of the type of x, or, if the type of x is a union type, removes from the type of x all constituent types that aren't subtypes of the type of the 'prototype' property in C, or
    • when false, has no effect on the type of x.

That said, I'm not aware of the rationale here to do no narrowing in the else clause, it seems like this should work. @ahejlsberg can weigh in.

@NoelAbrahams
Copy link

Seems related to #1719

@danquirk
Copy link
Member

danquirk commented Feb 6, 2015

Thought I had seen this before... don't know why I couldn't find it. Closing this as a dupe then.

@danquirk danquirk closed this as completed Feb 6, 2015
@danquirk danquirk added the Duplicate An existing issue was already created label Feb 6, 2015
@donnut
Copy link
Author

donnut commented Feb 9, 2015

Ok, this limits the usage of type guard to primitives only. Type guard

function(x: string|string[]) {
    if (x instanceof Array) {
       A(x);
    else {
       B(x);
    }
}

should be replaced by

function(x: string|string[]) {
    if (typeof x === 'string') {
       B(x);
    else {
       A(x);
    }
}

We are working with interfaces a lot, so I hope there will be a solution soon.
Thanks
(A TypeScript Fan)

@NoelAbrahams
Copy link

@danquirk, this may not be a duplicate. It's not about narrowing in the else block.

@NoelAbrahams
Copy link

This may be related to #1587, in which case it's fixed in 1.5.

@donnut, there's also a bug in there. once #1785 is fixed it should be possible to write

function(x: string|string[]) {
    if (x instanceof Array) {
       A(x);
    else {
       B(x);
    }
}

@donnut
Copy link
Author

donnut commented Feb 9, 2015

Thanks @NoelAbrahams. I just tried the example:

function(x: string|string[]) {
    if (x instanceof Array) {
       A(x);
    else {
       B(x);
    }
}

with the latest master, but the compiler still errors. Can you confirm this?

@donnut
Copy link
Author

donnut commented Feb 9, 2015

@danquirk
Copy link
Member

That would be #1719, the else block isn't getting a narrowed type by design at the moment.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants