In the following example, I am using a user-defined type guard function in order to filter an array. I want a strongly typed array of only Fish
.
The type are properly returned here, please note I am using a point free style:
const onlyFish = animals.filter(isFish); // Fish[]
The type are not properly returned here, It is a mixed array:
const onlyFish2 = animals.filter(x => isFish(x)); // (Fish | Bird)[]
- Why there is this different?
- How do you ensure the types are properly returned in onlyFish2 without doing
const onlyFish2: Fish[]
type Fish = {
variant: 'fish'
}
type Bird = {
variant: 'bird'
}
const isFish = (animal: Fish | Bird): animal is Fish => animal.variant === 'fish';
const animals: ReadonlyArray<Fish | Bird> = [{ variant: 'fish' }, { variant: 'bird' }];
const onlyFish = animals.filter(isFish); // Fish[]
const onlyFish2 = animals.filter(x => isFish(x)); // (Fish | Bird)[]
CodePudding user response:
The difference is the following:
const onlyFish = animals.filter(isFish);
Here, the result of the predicate will be x is Fish
and as such TypeScript can correctly deduce the type.
However, in this case:
const onlyFish2 = animals.filter(x => isFish(x));
The return value of your predicate is a boolean
as you are returning the result from your type guard: "is x a Fish?".