Reputation: 6853
I want to narrow down type based on the class property when calling array .filter
or .find
class Square {
type: "square";
constructor() {
this.type = "square";
}
}
class Circle {
type: "circle";
constructor() {
this.type = "circle";
}
}
const objects = [
new Circle(),
new Square(),
new Circle(),
new Square(),
];
// I want `circles` to be Circle[], not (Circle | Square)[]
const circles = objects.filter(o => o.type === "circle");
// I want `square` to be Square | undefined, not Circle | Square | undefined
const square = objects.find(o => o.type === "square");
Is this possible in TypeScript?
Upvotes: 2
Views: 373
Reputation: 1074335
You can do this with type guard functions. Here's an example with the type guard functions defined ahead of time:
function isSquare(obj: {type: string}): obj is Square {
return obj.type === "square";
}
function isCircle(obj: {type: string}): obj is Circle {
return obj.type === "circle";
}
// ...
// I want circles to be Circle[]
const circles = objects.filter(isCircle);
// I want square to be Square | undefined
const square = objects.find(isSquare);
...but they can also be inline:
// I want circles to be Circle[]
const circles = objects.filter((obj): obj is Circle => obj.type === "circle");
// I want square to be Square | undefined
const square = objects.find((obj): obj is Square => obj.type === "square");
Upvotes: 4