如何在 returns 作为其回调之一的函数的 Typescript 中声明类型?
How do I declare typings in Typescript of a function which returns a result of one of its callbacks?
我有一个 mapResponse
函数,它接受另一个函数(调用者)和一个映射器函数。该函数的结果应该是第三个函数,它是所提供回调的组合:它应该采用调用者的参数,但 returns 映射器的结果。
调用者可以产生 Promise,因此 Promise 应该在映射器获取他的参数之前解包。
所以我的问题不是实现(已经完成)而是类型。我如何用 Typescript 声明来描述这种行为?
export function mapResponse<
Caller extends (...args: any[]) => unknown,
Mapper extends <R>(response: Unpacked<ReturnType<Caller>>) => R
>(
caller: Caller,
mapper: Mapper
): (...args: Parameters<Caller>) => ReturnType<Mapper> {
return (...args: Parameters<Caller>) => {
const res = caller(...args) as Unpacked<ReturnType<Caller>>
if (res instanceof Promise) {
return res.then(mapper) as ReturnType<Mapper>
}
return mapper(res)
}
}
如果有人需要,这里是 Unpacked
声明:
export type Unpacked<T> = T extends (infer U)[]
? U : T extends (...args: any[]) => infer U
? U : T extends Promise<infer U>
? U : T
我将声明函数如下:
type Unpacked<T> = T extends Promise<infer U> ? U : T;
declare function mapResponse
<
TCaller extends (...args: any[]) => any,
TMapper extends (input: Unpacked<ReturnType<TCaller>>) => any
>(caller: TCaller, mapper: TMapper):
TMapper extends (input: Unpacked<ReturnType<TCaller>>) => infer R ? (...args: Parameters<TCaller>) => R : never;
const func1 = mapResponse((a: number, b: number) => a + b, sum => sum.toString()); // (a: number, b: number) => string
const func2 = mapResponse((a: number, b: number) => Promise.resolve(a + b), sum => sum.toString()); // (a: number, b: number) => string
与您的示例相比,不同之处在于 TMapper
右侧也必须具有 extends
定义,以便 infer R
正确。
此处为 TypeScript playground 示例:https://tsplay.dev/wOav6m
我有一个 mapResponse
函数,它接受另一个函数(调用者)和一个映射器函数。该函数的结果应该是第三个函数,它是所提供回调的组合:它应该采用调用者的参数,但 returns 映射器的结果。
调用者可以产生 Promise,因此 Promise 应该在映射器获取他的参数之前解包。
所以我的问题不是实现(已经完成)而是类型。我如何用 Typescript 声明来描述这种行为?
export function mapResponse<
Caller extends (...args: any[]) => unknown,
Mapper extends <R>(response: Unpacked<ReturnType<Caller>>) => R
>(
caller: Caller,
mapper: Mapper
): (...args: Parameters<Caller>) => ReturnType<Mapper> {
return (...args: Parameters<Caller>) => {
const res = caller(...args) as Unpacked<ReturnType<Caller>>
if (res instanceof Promise) {
return res.then(mapper) as ReturnType<Mapper>
}
return mapper(res)
}
}
如果有人需要,这里是 Unpacked
声明:
export type Unpacked<T> = T extends (infer U)[]
? U : T extends (...args: any[]) => infer U
? U : T extends Promise<infer U>
? U : T
我将声明函数如下:
type Unpacked<T> = T extends Promise<infer U> ? U : T;
declare function mapResponse
<
TCaller extends (...args: any[]) => any,
TMapper extends (input: Unpacked<ReturnType<TCaller>>) => any
>(caller: TCaller, mapper: TMapper):
TMapper extends (input: Unpacked<ReturnType<TCaller>>) => infer R ? (...args: Parameters<TCaller>) => R : never;
const func1 = mapResponse((a: number, b: number) => a + b, sum => sum.toString()); // (a: number, b: number) => string
const func2 = mapResponse((a: number, b: number) => Promise.resolve(a + b), sum => sum.toString()); // (a: number, b: number) => string
与您的示例相比,不同之处在于 TMapper
右侧也必须具有 extends
定义,以便 infer R
正确。
此处为 TypeScript playground 示例:https://tsplay.dev/wOav6m