[SOLVED] Build a function that accepts a Class in typescript

Issue

I’m trying to build a function that would take a class definition as a parameter in order to switch on it’s name

This is just to simplify my tests by creating one function that can generate data based on a given class

getMockDataForClass(c: Class, override){
   if(c === Person){ return getPersonMockData(override)}
   if(c === Dog){ return getDogMockData(override)}
...
}

so that I can write test like:

it('should process a persons information', ()=>{
   const p = getMockDataForClass(Person)
...
})

it('should compare 2 persons', ()=>{
   const p = getMockDataForClass(Person)
   const p2 = getMockDataForClass(Person, {name: 'Jane'})
})

However there doesn’t seem to be a type of class which would allow me to make this generic

Solution

Do you just want a "newable" type here?

type Class = {
    new (...args: unknown[]): unknown
    name: string // if you need it
}

Which works as you may expect:

class Person { person = true }
class Dog { dog = true }

function getMockDataForClass(c: Class, override: Class){
   if(c === Person) { return override}
   if(c === Dog){ return override }
   return c
}

getMockDataForClass(Person, Dog)

Playground


If you want the second argument to be an instance of the class that is the first argument, then you need to capture the class constructor as a generic parameter. And then the override is an instance of that class.

For instance:

type Class = {
    new (...args: any[]): unknown
}

class Person {
    constructor(public name: string) {}
}

class Dog {
    constructor(public breed: string) {}
}

function getMockDataForClass<T extends Class>(c: T, override: InstanceType<T>){
  //implementation...
}

getMockDataForClass(Person, {name: 'John'}) // fine
getMockDataForClass(Dog, {breed: 'Terrier'}) // fine
getMockDataForClass(Person, {breed: 'Terrier'}) // error

Playground

Answered By – Alex Wayne

Answer Checked By – Marilyn (BugsFixing Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *