【Node.js】execSyncの返り値からstderrを取得してエラーハンドリングしたい

困ったこと

Node.jsのchild_process.execSync()は他のexec()spawnSync()などと違いstderrを直接返してくれるわけではない。

import { execSync } from 'child_process';
function myCommand(command: string): string {
try {
return execSync(command).toString();
} catch (e: unknown) {
if (e instanceof Error) {
console.error(e.stderr.toString()); // Property 'stderr' does not exist on type 'Error'
}
throw e;
}
}

そのため例外処理の際にErrorオブジェクトから取得することになるが、もちろんそのままでは取得させてくれない。

if (e instanceof Error) {
if (e instanceof ExecException) { // 'ExecException' only refers to a type, but is being used as a value here.
console.error(e.stderr.toString());
}

更に組み込みのExecExceptionも型情報しか提供されてないため利用できない。

解決法

function hasStderr(err: any): err is { stderr: Buffer } {
return !!err.stderr;
}
if (e instanceof Error) {
if (hasStderr(e)) {
console.error(e.stderr.toString());
}

やや苦肉の策ではあるがユーザ定義型ガードを使う。

1

参考
  1. node.js - Async child_process.exec with TypeScript - Stack Overflow