JavaScript のデバッグ方法は多いです。debugger を埋め込む、開発者ツールでブレークポイントを追加する、開発者ツールでフレームワーク用の状態を見る、TypeScriptなどの AltJS で静的検査を行う、などです。これがテストの領域まで進むとJestなどの単体テストツールで問題の処理を抜き出して入出力と副作用を検証する、Playwrightなどのブラウザテストツールでブラウザ毎の挙動の違いを見る、などともっともっと広がります。そんな様々な方法ですが、最も手軽に導入できて最も利用者の多い方法は恐らくconsole.logによる printf 的なデバッグです。実際 console.log でのデバッグは非常に簡単です。この記事では console.log をアロー関数式の引数を見るために使う時にパパっと書ける方法を紹介します。
しばしば処理を簡単に書くために return を省略したアロー関数式を作る時があります。例えば、次です。
const exampleFn = (params) => params.length; exampleFn([1, 2, 3]);
これは React の中でコンポーネントを props で渡すときにもよく使います
<DatePicker
renderInput={(params) => (
<div>
<label>{params.label}</label>
<input value={params.value}>
</div>
)
/>
こういった時、渡した引数の中身を見たい時があります。手なりにconsole.logするために書き変えると次の様になります。
const exampleFn = (params) => {
console.log({params})
return params.length;
};
<DatePicker
renderInput={(params) => {
console.log({params})
return (
<div>
<label>{params.label}</label>
<input value={params.value}>
</div>
)
}
/>
return を省略したアロー関数を崩して二つの式を持つ文にすることでconsole.logと本来の処理を実行するようにします。正直めんどくさいです。楽するために最初 return を省略したのに、このデバッグで return を書いて、消して、とすることになってしまいます。
面倒でない手軽な書き方が次です。
const exampleFn = (params) => console.log({params}) || params.length;
<DatePicker
renderInput={(params) => console.log({params}) || (
<div>
<label>{params.label}</label>
<input value={params.value}>
</div>
)
/>
何をしているかというと JavaScript の論理和で二つの式をまとめて、必ず両方が実行される一つの式にしています。console.log は必ず falsy な値を返すので、本来の処理の方の式も評価され、処理を壊さずコードも大して変えずに console.log ができます。
素の JavaScript ならば上の方法を使えますが、TypeScript 上で同じ方法を使おうとすると次の様にエラーが出力されます。
// TS1345: An expression of type 'void' cannot be tested for truthiness.
const exampleFn = (params) => console.log({params}) || params.length;
void 型を比較に使うな、とかそんな感じのエラーです。先ほどのコードの様に falsy な値として実際は処理されますが void で比較すること自体が怪しい処理なので TypeScript はエラーを出してくれます。これの抜け道は次の様に作れます。
const exampleFn = (params: {length: number}) => ( console.log({params}) as any) || params.length;
as anyで void ではない、と宣言して無理やり黙らせます。 ちなみに void as false などとするとまた別のエラーが起きます。
その場で楽に console.xxx を仕込みたい時には楽な手法ですが、console.log は製品版に混じるべきでないコードです。こういった方法を使う時は併せて ESLint の no-console ルールなどを使って console が残るのを防止すべきです。