0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

関数をラップする関数を返す関数の型のメモ

Posted at

なんのこっちゃというタイトルですが

既存の関数の前後にログを仕込んだ新しい関数を作ったりなど、既存関数のシグネチャを保ったまま、新しい関数を作成したい場合があります。

その場合の型定義のメモです。

サンプル

function withXxxx<T extends any[], U>(
  func: (...args: T) => U
): (...args: T) => U {

  return function (...args: T) {
    return func(...args);
  };
}

既存関数の引数を T extends any[] で表し、戻り値をU としてそれをそのまま返すようにすれば良いです。

(ラップした関数から既存関数の名前が消えてしまうのがデメリットですが..)

実際の例

前後にログを仕込む関数の場合

function withLogging<T extends any[], U>(
  name: string,
  func: (...args: T) => U
): (...args: T) => U {
  return function (...args: T) {
    try {
      console.log(`${name}:begin`, ...args)
      const returnValue = func(...args);
      console.log(`${name}:end`, returnValue)
      return returnValue;
    } catch (e) {
      console.error(`${name}:error`, e)
      throw e;
    }
  };
}

// 2つの引数を加算する関数
function sum(left: number, right: number): number {
  return left + right
}

// 可変長引数の引数を加算する関数
function sumAll(...args: number[]): number {
  return args.reduce((p, c) => p + c)
}

// 共に元の関数と同一の型定義
const sumLog = withLogging("sum", sum)
const sumAllLog = withLogging("sumAll", sumAll)

console.log(sumLog(4, 2))
// sum:begin 4 2
// sum:end 6
// 6

console.log(sumAllLog(1,2,3,4,5,6,7,8,9,10))
// sumAll:begin 1 2 3 4 5 6 7 8 9 10
// sumAll:end 55
// 55

複数の関数をつなげると処理が追いにくくなるので、使用する場面は限られるかもしれないですが
覚えておくと何かの役に立つと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?