简体   繁体   中英

Typescript: custom type guard for generic type?

I have two related types and I want to distinguish between them with a custom type guard. They are generic types (in real life they take multiple type args but this is simplified for SO).

My question is this: is it possible to write a generic isCat type guard that returns a predicate that works (returns true) for any cat type Cat<T> ? In my real app there are many possible options for T so writing them all out isn't practical.

class Dog<T> {
  age: number|T = 1
  bark() { console.log("woof")}
}

class Cat<T> {
  age: number|T = 1
  meow() { console.log("meow")}
}

function isCat(animal: any): animal is Cat { // this is invalid, generic type Cat requires 1 arg
  return 'meow' in animal
}

function f(animal: any) {
  if (isCat(animal))
    animal.meow()
}
f(new Cat<number>())
f(new Dog<number>())

You can use the reserved word unknown to tell typescript that it's a Cat that have an unknown templated parameter

class Dog<T> {
  age: number|T = 1
  bark() { console.log("woof")}
}

class Cat<T> {
  age: number|T = 1
  meow() { console.log("meow")}
}

function isCat(animal: any): animal is Cat<unknown> {
  return 'meow' in animal;
}

function f(animal: any) {
  if (isCat(animal))
    animal.meow()
}

f(new Cat<number>())
f(new Dog<number>())

Also I would do something like:

class Animal<T> {
  age: number|T = 1
}

class Dog<T> extends Animal<T> {
  bark() {
    console.log('woof');
  }
}

class Cat<T> extends Animal<T> {
  meow() {
    console.log('meow');
  }
}

function isCat(animal: Animal<unknown>): animal is Cat<unknown> {
  return 'meow' in animal;
}

function f(animal: Animal<unknown>) {
  if (isCat(animal))
    animal.meow()
}

f(new Cat<number>())
f(new Dog<number>())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM