[英]How can I return the ReturnType of functions from a list of parameters in Typescript?
我有一个主函数myMainFunction()
,它接收函数列表作为参数。 这些参数函数中的每一个都可以有不同的返回类型。
我希望myMainFunction
将其返回类型作为作为参数传递给它的函数的返回类型。 但是,我不知道该怎么做。
这是我所拥有的似乎不起作用的东西:
const funcA = async (): string => "Hello";
const funcB = async (): {name: string, age: number} => ({ name: "Jane", age: 123 });
const myMainFunction = async <F extends () => ReturnType<F>>(...functions: F[]): Promise<ReturnType<F>[]> => {
const res = await Promise.all(functions.map((fn) => fn()));
return res;
};
// This doesn't work as values has a type of Promise<string>[]
// I'm expecting values to have a type of Promise<[string, {first: string, age: number }]>
const values = await myMainFunction(funcA, funcB);
我上面的内容不起作用,因为变量values
的类型是Promise<string>[]
。 由于某种原因,它只看到参数中第一个函数的返回类型。
我values
的类型为Promise<[string, {first: string, age: number }]>
,它们本质上是funcA()
和funcB()
的返回类型。
我怎样才能实现它?
Typescript 对数组类型T[number]
有一个特殊的类型,所以我们可以使用它->
const funcA = async (): Promise<string> => "Hello";
const funcB = async (): Promise<{name: string, age: number}> => ({ name: "Jane", age: 123 });
const myMainFunction = async <T extends any[number][]> (...functions: T) => {
const res = await Promise.all(functions);
return res;
};
async function test() {
const values = await myMainFunction(funcA(), funcB());
// values[0] string
// values[1] {name: string, age: number}
console.log(values[1].age);
}
传递函数时的问题,映射函数会丢失类型。 但是我们可以把它们放回去使用as
。 感谢@TJCrowder,我使用了他的 MapToUnpromisedReturnType 辅助类型并得到了这个 ->
const funcA = async (): Promise<string> => "Hello";
const funcB = async (): Promise<{name: string, age: number}> => ({ name: "Jane", age: 123 });
type MapToUnpromisedReturnType<T extends Array<any>> = {
[K in keyof T]: Awaited<ReturnType<T[K]>>;
};
const myMainFunction = async <T extends (() => Promise<any[number]>)[]> (...functions: T) => {
const mapped = await functions.map(f => f());
return mapped as MapToUnpromisedReturnType<T>;
};
async function test() {
const values = await myMainFunction(funcA, funcB);
// values[0] string
// values[1] {name: string, age: number}
console.log(values[1].age);
}
ps:可能有更清洁的方法,但它似乎工作得很好..
只是一个稍微重构的版本来带走助手->
const myMainFunction = async <T extends (() => Promise<any[number]>)[]> (...functions: T) => {
return functions.map(f => f()) as {[K in keyof T]: Awaited<ReturnType<T[K]>>};
};
type ResolveFunction<T extends (...args: any) => any> = Awaited<ReturnType<T>>;
type ResolveFunctions<T extends [...((...args: any) => any)[]]> = T extends [
infer Head,
...infer Tail
]
? Head extends (...args: any) => any
? Tail extends ((...args: any) => any)[]
? [ResolveFunction<Head>, ...ResolveFunctions<Tail>]
: []
: []
: [];
const myMainFunction = async <T extends [...((...args: any) => any)[]]>(
...functions: T
): Promise<ResolveFunctions<T>> => {
const res = await Promise.all(functions.map((fn) => fn()));
return res as any;
};
type AsyncFunction = (...args: any) => Promise<any>;
type ResolveFunction<T extends AsyncFunction> = Awaited<ReturnType<T>>;
type ResolveFunctions<T extends AsyncFunction[]> = {
[K in keyof T]: ResolveFunction<T[K]>;
};
const myMainFunction = async <T extends AsyncFunction[]>(
...functions: T
): Promise<ResolveFunctions<T>> => {
const res = await Promise.all(functions.map((fn) => fn()));
return res as any;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.