Home > OS >  Change type of an object's property based on another property's value in class variable
Change type of an object's property based on another property's value in class variable

Time:01-11

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
    }
}

Playground

  • Related