Typescript 泛化“中的类型脚本类型推断”;“承诺”;作用 上下文

Typescript 泛化“中的类型脚本类型推断”;“承诺”;作用 上下文,typescript,type-inference,typescript-typings,Typescript,Type Inference,Typescript Typings,最近我正在研究第三方图书馆的“promisification”。基本上,库中充满了NodeJS异步样式的函数(使用回调作为最后一个参数)。即具有类似于此签名的功能: 函数foo(arg1:string,arg2:number,…,回调:(错误,结果)=>void:void 我尝试编写一个函数,它将减少包装原始函数的代码,并使它们成为Promise返回函数: function cb<TResult>( resolve: (res: TResult) => void, re

最近我正在研究第三方图书馆的“promisification”。基本上,库中充满了NodeJS异步样式的函数(使用回调作为最后一个参数)。即具有类似于此签名的功能:

函数foo(arg1:string,arg2:number,…,回调:(错误,结果)=>void:void

我尝试编写一个函数,它将减少包装原始函数的代码,并使它们成为
Promise
返回函数:

function cb<TResult>(
  resolve: (res: TResult) => void,
  reject: (err: any) => void
): (actualError, actualResult) => void {

  return (error, result) => error ? reject(error) : resolve(result);
}

因为我处理的是TypeScript而不是JavaScript,所以我进一步做了一些研究。这就是我最终选择键入promisify的原因,代码现在看起来如下所示:

patchUserMetadata = promisify(this.wrapped.patchUserMetadata);

linkUser = promisify(this.wrapped.linkUser);
整洁多了,是吗

越来越近 我想知道这个
promisify
函数到底是如何工作的?我查看了源代码,发现了一个类似于js promisify的解决方案:

export function promisify<T>(f: (cb: (err: any, res: T) => void) => void, thisContext?: any): () => Promise<T>;
export function promisify<A, T>(f: (arg: A, cb: (err: any, res: T) => void) => void, thisContext?: any): (arg: A) => Promise<T>;
export function promisify<A, A2, T>(f: (arg: A, arg2: A2, cb: (err: any, res: T) => void) => void, thisContext?: any): (arg: A, arg2: A2) => Promise<T>;
// ...more overloads

export function promisify(f: any, thisContext?: any) {
  return function () {
    let args = Array.prototype.slice.call(arguments);
    return new Promise((resolve, reject) => {
      args.push((err: any, result: any) => err !== null ? reject(err) : resolve(result));
      f.apply(thisContext, args);
    });
  }
}

我有一种感觉,我正在寻找的是不可能实现的,这就是为什么长重载列表是作者不得不使用的最后手段/折衷解决方案。

从2.5版开始,在这个问题得到解决之前,目前在TypeScript中无法做到这一点:


在可变类型下,它已经出现了一段时间

非常感谢您参考TS问题和路线图文件!!现在有一种方法可以将具有基于回调的方法的类型转换为基于承诺的类型?
patchUserMetadata = promisify(this.wrapped.patchUserMetadata);

linkUser = promisify(this.wrapped.linkUser);
export function promisify<T>(f: (cb: (err: any, res: T) => void) => void, thisContext?: any): () => Promise<T>;
export function promisify<A, T>(f: (arg: A, cb: (err: any, res: T) => void) => void, thisContext?: any): (arg: A) => Promise<T>;
export function promisify<A, A2, T>(f: (arg: A, arg2: A2, cb: (err: any, res: T) => void) => void, thisContext?: any): (arg: A, arg2: A2) => Promise<T>;
// ...more overloads

export function promisify(f: any, thisContext?: any) {
  return function () {
    let args = Array.prototype.slice.call(arguments);
    return new Promise((resolve, reject) => {
      args.push((err: any, result: any) => err !== null ? reject(err) : resolve(result));
      f.apply(thisContext, args);
    });
  }
}
export function promisify<...[TArgs], T>(
  f: (...allArgsButLastTwo: [TArgs],
  cb: (err: any, res: T) => void) => void,
  thisContext?: any
): (...[TArgs]) => Promise<T>;

export function promisify(
  ...allArgsButLastTwo: any[],
  f: any,
  thisContext?: any
) {
  return function () {
    let args = Array.prototype.slice.call(arguments);
    return new Promise((resolve, reject) => {
      args.push((err: any, result: any) => err !== null ? reject(err) : resolve(result));
      f.apply(thisContext, args);
    });
  }
}