TypeScript Util系モジュールのまとめ方


TypeScriptで状態を持たない単なるヘルパー関数を追加するとき、どのようにモジュール構成を取るかブレブレでした。

  • 外部に公開しないモジュール
  • 外部で使えるモジュール

この2つがあるとして、大きく分別した場合に以下の3パターンに分けられそうです。

1. それぞれexport

util-calc.ts
const log = (message: string): void => {
  console.log(message);
};

export const add = (a: number, b: number): number => {
  log('add method execute.');

  return a + b;
};

export const minus = (a: number, b: number): number => {
  log('minus method execute.');

  return a - b;
};

メリット

  • 最もシンプルで、ひと目で分かる。

デメリット

  • 名前空間を持たせたい場合はimport as使わないといけない。

2. 1つのオブジェクト

1と類似。これもよくあり得るパターンだと思います。

utilCalc.ts
const log = (message: string): void => {
  console.log(message);
};

const utilCalc = {
  add: (a: number, b: number): number => {
    log('add method execute.');

    return a + b;
  },

  minus: (a: number, b: number): number => {
    log('minus method execute.');

    return a - b;
  },
};

export default utilCalc;

メリット

  • 公開する場所が的確

デメリット

  • JSに慣れない人には見づらい?

3. Static method

UtilCalc.ts
export default class UtilCalc {
  private static log(message: string): void {
    console.log(message);
  }

  public static add(a: number, b: number): number {
    this.log('add method execute.');

    return a + b;
  }

  public static minus(a: number, b: number): number {
    this.log('minus method execute.');

    return a - b;
  }
}

メリット

  • オブジェクト指向のバックグラウンドに最も馴染みやすい
  • モックで差し替えてテストコードを書きやすい?(あまり検証していません)

デメリット

  • JSだけの経験者には見づらいかも

おわりに

基本的に名前空間不要なら1, 名前空間欲しいなら2の方針がJSとしてスタンダードなのでしょうが、リポジトリを見ると案外クラスを使ったコードもあり、3も利点を見出した方が良いのかとも考えます。