Home > Software design >  Generic types in classes
Generic types in classes

Time:11-05

I'm trying to implement generic types into classes but it turns out that I'm lacking understanding of what you can and cannot do with generics.

Hopefully someone can help me with this!

What I want

I have created a class which is supposed to register tasks and run them later by id. A taskObject consists of taskId: string and a callback function callback: <R>(...args: any) => R. Tasks will be registered when instantiating the class.

The idea is that I have type information about the return type of the callback function for each individual task.

So taskId is a literal type and callback ist supposed to be an arbitrary function for which I want to infer the return type and make this return type accessible within my class.

The code


type Task<T extends string, V extends <R>(...args: any) => R> = {
  taskId: T
  callback: V // <-- I would like this resolved
}

class Taskmanager<T extends string, V extends <R>(...args: any) => R> {

  private callbacks = new Map<T, V>();

  public constructor(tasks: Task<T,V>[]) {
    tasks.forEach(task => {
      this.callbacks.set(task.taskId, task.callback);
    });
  }

  public runCallback(taskId: T) {
    return this.callbacks.get(taskId)?();
  }
}

This kind of does the first step → I have type hints for all registered taskIds.

const tm = new Taskmanager([
  {
    taskId: "hello",
    callback: () => "world" // <-- TS error: Type 'string' is not assignable to type 'R'
  },
  {
    taskId: "circle",
    callback: () => 360 // <-- TS error: Type 'number' is not assignable to type 'R'
  }
]);

// I'm now getting type hints for `taskId` → "hello" | "circle"
const resHello = tm.runCallback("hello"); // <-- I would like: typeof resHello === "string" --> true
const resCircle = tm.runCallback("hello"); // <-- I would like: typeof resCircle === "number" --> true

Here's a TS Playground link

Which gives me the expected result that I'm only allowed to choose between hello and circle as parameter in runCallback. However, I'm getting TS errors when declaring the callback functions in the class constructor.

// TS Error for taskId: "hello"
Type 'string' is not assignable to type 'R'.
  'R' could be instantiated with an arbitrary type which could be unrelated to 'string'.

Is there a way to infer the return type of each callback function? Is this even possible?

I did check a couple other questions and answers here on StackOverflow but unfortunately I could not extract anything useful so far.

I apologise if this question is stupid. TS really drives me crazy sometimes...

Thank you!

  • Related