Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript type check not working with Array filter

I am using Array.filter and instanceof to get all the objects of a certain type out of a more generic array.

 let cars:Car[] = this.gameObjects.filter(go => go instanceof Car)

This works! But the typescript compiler doesn't agree that the returned types are all of the Car type.

Type 'GameObject[]' is not assignable to type 'Car[]'

On the Typescript GitHub this issue is considered solved by adding an interface for array.filter. That doesn't work for me, it still gives the same error. You can try it out by pasting this code in the typescript playground:

interface Array<T> {
    filter<U extends T>(pred: (a: T) => a is U): U[];
}

class Car { 
    drive() { 

    }
}
class GameObject { 

}

let gameObjects:GameObject[] = [new Car(), new Car()]

let cars:Car[] = gameObjects.filter((go) => go instanceof Car)

Am I missing something here? How can I filter an array by type and get back an array of the correct type?

like image 453
Kokodoko Avatar asked May 27 '19 12:05

Kokodoko


1 Answers

To change the return type on filter function you must use a Type Guard Function like the following. You also don't need to extend the Array type because that's already defined on TypeScript.

class GameObject { 

}

class Car { 
    drive() { 

    }
}

let isCar = (obj: any): obj is Car => {
    return obj instanceof Car;
}

let gameObjects: GameObject[] = [new Car(), new Car()]

let cars: Car[] = gameObjects.filter(isCar)
like image 112
goenning Avatar answered Oct 24 '22 20:10

goenning