TL;DR TypeScript type inference fails in class when using union types
I've ran into an issue with typescript when dealing with classes and union types.
This is a basic version of the types that i've got:
type CommonData = {
name: string
}
type Dog = {
age: number
} & CommonData
type Bat = {
wingspan: number
} & CommonData
type Animal = {
type: "dog"
data: Dog
} | {
type: "bat"
data: Bat
}
The Animal
type changes its data type based on the value of the type field.
So, when creating objects using the Animal
type, typescript is able to determine what type of data is used for each animal based on the type field. Example below:
const bat: Animal = {
type: "bat",
data: {
name: "tim",
wingspan: 9000
}
}
// has type inference,
bat.data.name
However, when implementing the same type in a class, typescript doesn't recognize what type of data is returned. Here's an example of what my current code is like:
class AnimalClass {
animal: Animal
constructor (animal: Animal) {
this.animal = animal
}
}
const dog = new AnimalClass({
type: "dog",
data: {
name: "bob",
age: 10
}
})
// no type inference on data, typescript doesn't know that it's a Dog
dog.animal.data
dog.animal.data has a type of Dog | Bat
. Is it possible to alter the code to infer that the type of dog.animal.data is Dog
Thanks in advance :)
Here's the full code: Typescript Playground
CodePudding user response:
You can use a generic annotaion on the Animal class as the following, to make the inference complete:
class AnimalClass<T extends Animal> {
animal: T;
constructor (animal: T) {
this.animal = animal
}
}