How do I assign the generic type parameter for a function to a typeguard type from a function's typeguard? Is there some sort of typescript TypeguardType<matcher>
helper to assist with this?
Something like this:
function findAnimal<TAnimal = TypeguardType<matcher>>(animals: Array<any>, matcher: (animal: any) => boolean) {
return animals.find(matcher) as TAnimal;
}
Here's a full example with usage.
class Dog {
bark() { }
}
class Cat {
meow() { }
}
function isDog(animal): animal is Dog {
return !!animal.bark;
}
function isCat(animal): animal is Cat {
return !!animal.meow;
}
/**
* Return the first animal where the matcher evaluates to true
*/
function findAnimal<TAnimal>(animals: Array<any>, matcher: (animal: any) => boolean) {
return animals.find(matcher) as TAnimal;
}
const animals = [new Dog(), new Cat()];
//what I have to do (explicitly define a generic parameter)
const dog1 = findAnimal<Dog>(animals, isDog);
//what I want to do (typescript infer the return type from typeguard of matcher)
const dog2 = findAnimal(animals, isDog);
CodePudding user response:
You can use a generic type inside a type predicate to give you the behavior you're looking for:
function findAnimal<T>(animals: any[], matcher: (animal: any) => animal is T) {
return animals.find(matcher)
}
// function findAnimal<T>(
// animals: any[], matcher: (animal: any) => animal is T
// ): T | undefined
That returns T | undefined
because the find()
array method isn't guaranteed to succeed, so it either returns a T
on success or undefined
on failure. Anyway, let's test it:
const dog = findAnimal(animals, isDog);
// const dog: Dog | undefined;
Looks good!