TypeScript 5.2 で追加された using を利用して、開始・終了のログを出力する

TypeScript 5.2 で追加された using を利用して、開始・終了のログを出力する方法のメモです。

結論

type Logger = {
log: (message: string) => void;
[Symbol.dispose]: () => void;
};
const getLogger = (processName: string): Logger => {
console.log(`start: ${processName}`);
return {
log: (message) => {
console.log(message);
},
[Symbol.dispose]: (...args) => {
console.log(`end: ${processName}`);
},
};
};
// Example
function process(input: string) {
using logger = getLogger('process');
if (input === '') {
logger.log('input is empty');
return;
}
logger.log('do process');
}
process('hoge');
// start: process
// do process
// end: process
process('');
// start: process
// input is empty
// end: process

解説

using は本来はリソースの解放を忘れずに行うための構文ですが、基本的には try..finally の糖衣構文のはずなので、こういう使い方をすることもできます。
少なくとも TypeScript では try..catch..finally に変換されることを確認できます。気になれば Playground で試してみてください。

console.log の場所を置き換えれば時間計測などにも使えると思います。(おまけに載せてます)

メリット

メリットとしては以下のような点が挙げられます。

  • 早期リターンなどで関数が途中で終了した場合でも、必ず終了のログが出力される
    • 同様のことを他の方法でやるとなると、try .. finally や高階関数などが必要になるため面倒
  • 1行だけでログ出力を行えるので、計測などでサッと入れたい場合に便利

おまけ (時間計測Ver)

const getTimer = (processName: string) => {
const start = performance.now();
console.log(`start: ${processName}`);
return {
[Symbol.dispose]: () => {
const end = performance.now();
console.log(`end: ${processName}: ${(end - start).toFixed(4)}ms`);
},
};
};
function process() {
using _ = getTimer('process');
for (let i = 0; i < 1000000000; i++) {
Math.sqrt(i);
}
}
process();
// start: process
// end: process: 330.6357ms