gpt4 book ai didi

typescript - 在 typescript 中使用回调来 promise 函数

转载 作者:搜寻专家 更新时间:2023-10-30 21:10:15 25 4
gpt4 key购买 nike

我有一个类在接受回调的方法上有多个重载。我想让它们基于Promise,但是我在使用 TypeScript 泛型以类型安全的方式执行此操作时遇到了麻烦。

基本上 API 是这样的:

class CallbackClient {
method(req: Request, callback: (error: Error, response: Response) => void): void
method(req: Request, options: Options, callback: (error: Error, response: Response) => void): void
}

应该变成这样:

class PromiseClient {
method(req: Request): Promise<Response>
method(req: Request, options: Options): Promise<Response>
}

但是如何在 TypeScript 中将 PromiseClient 定义为通用类型?在伪代码中,我想要这样的类型:

type PromiseClient<T> = {
[P in keyof T]: (args of T[P] without the callback) => Promise<response of T[P] in callback>
}

我有一个实现可以做到这一点,但由于我无法实现这一点,我失去了类型安全。

映射它的函数是这样的:

function toPromiseClient<T extends CallbackClient>(client: T): PromiseClient<T> {
const promiseClient: PromiseClient<T> = {}
Object.keys(Object.getPrototypeOf(client))
.forEach((functionName: string) => {
const originalFunction = client[functionName as keyof T]
if (!originalFunction) {
return
}
promiseClient[functionName as keyof T] = (...args: any[]) => new Promise<any>((resolve, reject) => {
if (args && args.length > 1 && typeof (args[args.length - 1]) === 'function') {
reject(new Error('Use Promise API instead of callbacks'))
return
}
originalFunction.call(client, ...args, (error: Error, res: any) => {
if (error) {
reject(error)
return
}
resolve(res)
})
})
})
return promiseClient
}

最佳答案

这在 typescript 2.8 中是部分可行的(尚未发布,应该在 2018 年 3 月发布,你可以通过 npm install -g typescript@next 获取)

解决方法:

declare class CallbackClient {
method1(req: Request, options: Options, callback: (error: Error, response: Response) => void): void
method1(req: Request, callback: (error: Error, response: Response) => void): void


method2(req: Request, options: Options, callback: (error: Error, response: Response) => void): void

method3(req: Request, options?: Options, callback?: (error: Error, response: Response) => void): void
}

type Promisify<T> = {
[P in keyof T]:
T[P] extends (callback: (error: Error, response: infer TResponse) => void) => void ? () => Promise<TResponse> :
T[P] extends (p1: infer P1, callback: (error: Error, response: infer TResponse) => void) => void ? (p1: P1) => Promise<TResponse> :
T[P] extends (p1: infer P1, p2: infer P2, callback: (error: Error, response: infer TResponse) => void) => void ? (p1: P1, p2: P2) => Promise<TResponse> :
T[P] extends (p1: infer P1, p2: infer P2, p3: infer P3, callback: (error: Error, response: infer TResponse) => void) => void ? (p1: P1, p2: P2, p3: P3) => Promise<TResponse> :
never;
}

type PromiseClient = Promisify<CallbackClient>;
// Will be equivalent to :
// type PromiseClient = {
// method1: (p1: Request) => Promise<Response>; // Only one overload, not the second
// method2: (p1: Request, p2: Options) => Promise<Response>;
// method3: (p1: Request, p2: Options | undefined) => Promise<Response>;
// }

上面的解决方案使用条件类型从原始类的每个方法中提取参数类型,然后使用这些类型为返回 promise 的方法创建新的函数类型。

限制:

  1. 它不适用于任意数量的参数,上述解决方案最多适用于 3 个参数和回调,但您可以添加更多
  2. 参数名丢失
  3. 如果参数是可选的,它们将成为必需的,其类型为 ArgType | undefined
  4. 如果一个方法有多个重载,只有参数最少的那个才会进入结果。在上面的例子中,我们只得到了method1: (p1: Request) => Promise<Response>我们也没有得到 method1: (p1: Request, p2: Options) => Promise<Response> (根据重载的顺序,您可能会得到奇怪的结果,这很古怪)。

关于typescript - 在 typescript 中使用回调来 promise 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49303695/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com