Home > OS >  Get the type guard type from a type guarded function
Get the type guard type from a type guarded function

Time:10-06

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!

Playground link to code

  • Related