Skip to content

Array.filter with a user-defined type guard predicate (arrow function) resolves to the wrong overload #20218

New issue

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

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

Already on GitHub? # to your account

Closed
afroozeh opened this issue Nov 22, 2017 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@afroozeh
Copy link

afroozeh commented Nov 22, 2017

TypeScript Version: 2.6.1

Code

interface Animal {
}

interface Cat extends Animal {
  meow(): void;
}

interface Dog extends Animal {
  bark(): void;
}

function isCat(animal: Animal): animal is Cat {
  return animal.hasOwnProperty("meow");
}

function isDog(animal: Animal): animal is Dog {
  return animal.hasOwnProperty("bark");
}

let animals: Animal[];

const cats: Cat[] = animals.filter(isCat);            // OK
const cats2: Cat[] = animals.filter(a => isCat(a));   // Type error

Expected behavior:
No errors

Actual behavior:

Error at cats2:

[ts]
Type 'Animal[]' is not assignable to type 'Cat[]'.
  Type 'Animal' is not assignable to type 'Cat'.
    Property 'meow' is missing in type 'Animal'.

The first call to filter on animals resolves to the function

filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];

while the second call resolves to:

filter(callbackfn: (value: T, index: number, array: T[]) => any, thisArg?: any): T[];
@ghost
Copy link

ghost commented Nov 22, 2017

Duplicate of #5101 -- a => isCat(a) isn't explicitly annotated as being a type predicate, and we don't infer those.

@ghost ghost added the Duplicate An existing issue was already created label Nov 22, 2017
@afroozeh
Copy link
Author

A question: what's the difference between animals.filter(isCat) and animals.filter(a => isCat(a))? I thought the first one is a syntactic sugar for the second one, when there is only argument.

@ghost
Copy link

ghost commented Nov 22, 2017

a => isCat(a) is a function literal expression that creates a new function. isCat is an identifier referring to an existing function. isCat has a type annotation declaring it to be a type predicate, but a => isCat(a) has no type annotations and relies on type inference. We will never infer a type predicate type, only boolean (#5101).

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
# for free to subscribe to this conversation on GitHub. Already have an account? #.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants