Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to dynamically set the type of constructor function method in TypeScript

I am trying to create a class or constructor function, which I specify a list of values to be used in the type of one of it’s methods.

As an example I have this code.

const MyAnimal = function (animal: string[]) {
  type Animal = typeof animal[number]

  this.getAnimal = (url: Animal) => {
    console.log(url)
  }
}

const animalTest = new MyAnimal(['sheep', 'dog', 'cat'])
// I would like this to fail as 'mouse' is not part of the array ['sheep', 'dog', 'cat']
animalTest.getAnimal('mouse')

I want getAnimal to have the type 'sheep' | 'dog' | 'cat' and for the intellisense to warn me if I add something different

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Is this possible?

>Solution :

You can do that via a generic type parameter and a readonly array of animals, like this;

class MyAnimal<Animal> {
    constructor(public animals: readonly Animal[]) {
    }
    getAnimal(url: Animal) {
        console.log(url);
    }
}

const animalTest = new MyAnimal(['sheep', 'dog', 'cat'] as const);
animalTest.getAnimal('mouse'); // Error as desired
animalTest.getAnimal('sheep'); // Works

Playground link

TypeScript can infer the string literal union type to provide as the type argument for the Animal type parameter because the array is readonly (which we satisfy when calling the constructor via as const), so TypeScript knows it won’t change at runtime.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading