Open4
JavaScript (Deno) で `cause` がチェーンされた Error をいい感じにテキスト表現で取得したい場合、`Deno.inspect` が便利
以下のようなコードがあるとする
class MyError extends Error {
constructor(cause: unknown) {
super("myerror!");
this.name = "MyError";
this.cause = cause;
}
}
function throwError() {
const e1 = new Error("e1");
const e2 = new Error("e2", { cause: e1 });
const myError = new MyError(e2);
throw myError;
}
try {
throwError();
} catch (e: unknown) {
console.log(e);
}
ES2022で追加された cause
プロパティを使って、3段階にネストされた Error
を作ってthrowし、それをキャッチしている。
cause
についての参考記事:
これをDeno (v2.1.5) で実行すると、以下のような出力になる
❯ deno run error_chain.ts
MyError: myerror!
at throwError (file:///private/tmp/error_chain.ts:12:19)
at file:///private/tmp/error_chain.ts:17:3
Caused by Error: e2
at throwError (file:///private/tmp/error_chain.ts:11:14)
at file:///private/tmp/error_chain.ts:17:3
Caused by Error: e1
at throwError (file:///private/tmp/error_chain.ts:10:14)
at file:///private/tmp/error_chain.ts:17:3 {
name: "MyError"
}
MyError -> e2 -> e1 というエラーの連鎖が正しく保持されている。
一方、console.log(e)
ではなく console.log(e.toString())
にすると、出力が変わる
❯ deno run error_chain.ts
MyError: myerror!
情報量が足りない…
console.log(e)
のときと同じリッチな情報を文字列として得たい場合、どうすればよいか?
Deno.inspect
というAPIがある
Converts the input into a string that has the same format as printed by console.log().
とあるように、引数で与えられた入力を、console.log
に渡したときと同じフォーマットの文字列に変換して返してくれる。
try {
throwError();
} catch (e: unknown) {
const s = Deno.inspect(e);
await Deno.stdout.write(new TextEncoder().encode(s));
}
のようにすれば、console.log(e)
したときと同じ文字列が得られていることが確認できる[1]:
❯ deno run error_chain.ts
MyError: myerror!
at throwError (file:///private/tmp/error_chain.mts:14:19)
at file:///private/tmp/error_chain.mts:19:3
Caused by Error: e2
at throwError (file:///private/tmp/error_chain.mts:13:14)
at file:///private/tmp/error_chain.mts:19:3
Caused by Error: e1
at throwError (file:///private/tmp/error_chain.mts:12:14)
at file:///private/tmp/error_chain.mts:19:3 {
name: "MyError"
}
-
標準出力への出力にconsole.logを使っていないのは、console.logによるフォーマットが効いているのではなく、
Deno.inspect
によるフォーマットが行われていることを明確にするため ↩︎
Node.js だと util.inspect
を使えば良さそう