繁体   English   中英

TypeScript 包装器 function 附加参数

[英]TypeScript wrapper function with additional parameters

我想为 TypeScript 中现有的 function 创建一个包装器 function。

包装器 function 可以启动一些其他进程,并在完成传递给包装器的主要(“回调”)function 后清理它。

这可以使用此处所示的方法来完成。 但是,这些解决方案不允许我指定可以传递给包装器本身的其他选项。

我将如何 go 这样做?

我的出发点是:

export const wrap = async <T>(
  callback: () => T | Promise<T>,
  options?: { foo?: string | undefined },
): Promise<T> => {
  let ret;

  // begin
  if (options.foo) {
    // do something
  }

  try {
    ret = await callback();
  } catch (e) {
    throw e;
  } finally {
    // cleanup
  }

  return ret;
};

这不会让我将 arguments 添加到callback() 我可以使用...args ,但如何同时指定...argsoptions

我建议你把你的 function 写成一个工厂(返回另一个函数的函数):

function wrap<T extends (...args: any[]) => any>(callback: T, options?: { foo?: string | undefined }): (...args: Parameters<T>) => ReturnType<T> extends Promise<infer U> ? Promise<U> : Promise<ReturnType<T>>
function wrap(callback: (...args: any[]) => any, options?: { foo?: string | undefined }): (...args: any[]) => Promise<any> {

  return async function (...args: any[]) {
    let ret;

    // begin
    if (options && options.foo) {
      // do something
    }

    try {
      ret = await callback(...args);
    } catch (e) {
      throw e;
    } finally {
      // cleanup
    }

    return ret;
  }
};

async function asyncExtractFirstParameter(str: string, num: number, bool: boolean) {
  return str;
}

function extractFirstParameter(str: string, num: number, bool: boolean) {
  return str;
}

const wrappedAsyncExtractFirstParameter = wrap(asyncExtractFirstParameter);
const wrappedExtractFirstParameter = wrap(extractFirstParameter);

wrappedAsyncExtractFirstParameter('test', 23, true).then(console.log);
wrappedExtractFirstParameter('test', 23, true).then(console.log);

这允许您创建另一个 function 与回调具有相同的签名,并可能推迟其执行。

TypeScript 操场

该解决方案包括使函数通用 ( F ) 并通过ReturnTypeParameters推断该 function 的参数和返回类型。 可以在传递给callback function 的解构剩余 arguments 之前指定任何其他选项:

export const wrap = async <F extends (...args: any[]) => ReturnType<F> | Promise<ReturnType<F>>>(
  callback: F,
  options: { foo?: string | undefined } = {},
  ...args: Parameters<F>
): Promise<ReturnType<F>> => {
  let ret: ReturnType<F> | undefined;

  // begin
  if (options.foo) {
    // do something
  }

  try {
    ret = await callback(...args);
  } catch (e) {
    throw e;
  } finally {
    // cleanup
  }

  return ret;
};

然后可以像这样调用包装器:

const someFunction = (arg1: string, arg2: boolean): void => {
  // do something
}

wrap(someFunction, { foo: "yes" }, arg1, arg2)`

所有返回类型和参数类型都是自动推断的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM