Reputation: 7506
I have a function which takes a variable number of input parameters and returns an array of the same length, with the items having the generic types specified when the function is called. It's actually a function which returns a Promise
array.
Using mapped types I did this:
export const Service = {
/* ... */
promisify: <T extends [] = any>(...p: Array<string>): { [P in keyof T]: Promise<T[P]> } => {
const result = [];
/* ... */
return result;
}
}
but it's giving an error because an object is declared as the return type...
What I'm trying to achieve is someting allong these lines:
/*pseudocode*/
export const Service = {
promisify: <T extends [] = any>(...p: Array<string>): [ [P in keyof T]: Promise<T[P]> ] => {
const result = [];
/* ... */
return result;
}
}
The result I'm after is being able to call this function and have the right return type:
Service.promisify<number>("val1"); //=> [Promise<number>]
Service.promisify<number, string>("val1", "val2"); //=> [Promise<number>, Promise<string>]
Service.promisify<number, string, MyType>("val1", "val2", "val3"); //=> [Promise<number>, Promise<string>, Promise<MyType>]
Is this currently possible using mapped types or do I need to specifiy overloads?
Upvotes: 1
Views: 243
Reputation: 249646
Your general idea should work, you just have a couple of issues around syntax. There is no mapped tuple syntax, but regular mapped types work with tuples as expected (since 3.1 I believe).
Also you need to constrain T
to be an array type, and you will need to pass in the types you want to map as a tuple:
export const Service = {
promisify: <T extends any[]>(): { [P in keyof T]: Promise<T[P]> } => {
const result = [] as any as { [P in keyof T]: Promise<T[P]> };
/* ... */
return result;
}
}
Service.promisify<[number]>(); //=> [Promise<number>]
Service.promisify<[number, string]>(); //=> [Promise<number>, Promise<string>]
Service.promisify<[number, string, MyType]>(); //=> [Promise<number>, Promise<string>, Promise<MyType>]
Upvotes: 1
Reputation: 3061
promisify()
returns an object. If you want to return an object, initialize it with {}
and define its type with as MyType
, the method return type will be inferred. I also prefer A[]
(more Typescript way) instead of Array<A>
(more C#/Java way):
promisify: <T extends [] = any>(...p: string[]) => {
const result = {} as { [P in keyof T]: Promise<T[P]> };
/* ... */
return result;
}
Upvotes: 0