Open Techn1x opened 1 year ago
Hi @Techn1x,
I have the same issue on my side, I could create a sample reproduction:
import Service from '@ember/service';
import { task, timeout } from 'ember-concurrency';
export default class Test extends Service {
createTask = task(
{ enqueue: true, maxConcurrency: 2 },
async <H, K extends keyof H>(hash: H, key: K): Promise<H[K]> => {
await timeout(100);
return hash[key];
}
);
async withoutTask<H, K extends keyof H>(hash: H, key: K): Promise<H[K]> {
await timeout(100);
return hash[key];
}
async test() {
const a = await this.withoutTask({ a: 'string', b: 12 }, 'a');
console.log(a);
const res = await this.createTask.perform({ a: 'string', b: 12 }, 'a');
console.log(res);
}
}
// DO NOT DELETE: this is how TypeScript knows how to look up your services.
declare module '@ember/service' {
interface Registry {
test: Test;
}
}
Let me know If I can help here.
Hi @Techn1x,
I think this is a limit of typescript... I did a lot of trial and error on the typescript playground, and here is a workaround that could work (forcing the type manually on the task).
const f = async <H, K extends keyof H>(h: H, k: K): Promise<H[K]> => {
return h[k];
}
const res = f({a: 'string', b: 12}, 'b');
const task = <H,K extends keyof H>(f: (...args: [H, K])=> Promise<H[K]>): {process: (h: H, k: K)=> Promise<H[K]> } => {
return {
process: (h: H, k: K): Promise<H[K]>=> {
return f(h, k);
}
}
}
type HackedTask = { process: <H,K extends keyof H>(h: H, k: K)=> Promise<H[K]> };
const t = (task(f) as unknown) as HackedTask;
const r = t.process({ a: 'string', b: true}, 'b');
I'm trying to build a typed task that returns the same type that it was performed with
For example;
I've come up with this as the task definition;
But I can't seem to get the return type from the perform call to be generic, it seems stuck as
unknown
. Is there a way to do what I am trying to acheive?It's probably got something to do with writing a Task type like this, but I can't quite figure out how to apply it to the task definition..