Open3

TypeScriptのユーティリティ

moshmosh

このスクラップの投稿はMIT-0でライセンスします。
MIT-0なので特に断りなく、コピーしても問題ありません!

moshmosh

エラーの原因を再帰的にたどりながらスタックを取得する関数。

/**
 * causeを含めてエラーのスタックトレースを取得します。
 * 
 * @example
 * const throwError1 = () => {
 *   throw Error('Error 1');
 * };
 * 
 * const throwError2 = () => {
 *   try {
 *    throwError1();
 *   } catch (e) {
 *    throw Error('Error 2', { cause: e });
 *   }
 * };
 * 
 * try {
 *  throwError2();
 * } catch (e) {
 *   console.log(chainCauseStacks(e));
 *   // Error: Error 2
 *   //     at throwError2 (<anonymous>:9:10)
 *   //     at <anonymous>:14:2
 *   // Caused by: Error: Error 1
 *   //     at throwError1 (<anonymous>:2:9)
 *   //     at throwError2 (<anonymous>:7:4)
 *   //     at <anonymous>:14:2
 * }
 */
const chainCauseStacks = (error: Error): string => { 
  let e: unknown = error;
  const stacks: string[] = [];
  while (e) {
    if (e instanceof Error) {
      if (typeof e.stack === 'string') {
        stacks.push(e.stack);
        e = e.cause;
      } else {
        break;
      }
    } else {
      stacks.push(String(e));
      break;
    }
  }

  return stacks.join('\nCaused by: ');
}

@exampleに書いているように、causeを辿ってstackを取得します。
エラーをチェインするライブラリと ES2022 Error Cause』に記載されていたFirefoxのエラー表示形式を参考にしています。

causeはES2022で追加されたErrorの原因を表すプロパティです。
ref. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause

moshmosh

Kotlinのスコープ関数のようなものをすべてのオブジェクトに追加します。[1]

declare interface Object {
  run<T, R>(this: T, f: (it: T) => R): R;
}

Object.getPrototypeOf({}).run = function <T, R>(this: T, f: (it: T) => R): R { 
  return f(this);
};

こんな感じでメソッドでない関数をメソッドチェイン風に繋ぐことができます!

/** `n`の絶対値を返す。`n`が`undefined`であるとき`undefined`を返す。 */
const abs = (n: number | undefined): number | undefined => {
  return n?.run(it => Math.abs(it));
};

console.log(abs(-1)); // 1
console.log(abs(undefined)); // undefined

gist: https://gist.github.com/moshg/64d72a3541710fb75626e78cd90a5e38

脚注
  1. スコープ関数を知らない人向けの解説:【Kotlin】let, with, run, apply, alsoの概要と違い、使い分け【スコープ関数解説】
    ↩︎