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!