How do I get TypeScript to recognize that the value of one field in a class restricts the type of another?
Example code (playground):
class Cat { purr() {/*...*/} }
class Dog { bark() {/*...*/} }
interface TypeMap {
cat: Cat;
dog: Dog;
}
class Pet<C extends keyof TypeMap> {
commonName: C;
animal: TypeMap[C];
constructor(commonName : C, animal: TypeMap[C]) {
this.commonName = commonName;
/*
//Dropping the parameter and trying to create the object here doesn't work:
if(commonName === 'cat') {
this.animal = new Cat();
} //...
// because Type 'Cat' is not assignable to type 'Cat & Dog'.
*/
this.animal = animal;
}
makeSound() {
if(this.commonName === 'cat') {
//Error: this.animal is of type 'Cat | Dog',
//not narrowed to Cat as hoped.
return this.animal.purr();
} else if (this.commonName === 'dog') {
//Error: this.animal is of type 'Cat | Dog',
//not narrowed to Dog as hoped.
return this.animal.bark();
}
}
}
The type of restriction shown in makeSound() is an example of what I'm trying to accomplish - where you should be able to inspect commonName to learn more about the type of this.animal in a way that narrows its type.
A related question about function parameters is here.