'Async child_process.exec with TypeScript

I'm trying to use a child_process.exec call with TypeScript, and error handling seems excessively hard to get right.

Here's the gist of what I'm trying to do:

import { promisify } from "util";
import { exec, ExecException } from "child_process";

const execPromise = promisify(exec);

export const myCommand = async (param: string) => {
  const { stdout, stderr } = await execPromise(`my_command ${param}`);
  return {
    stdout,
    stderr,
    // some other fields
  };
};

This works fine as long as my_command returns 0.

Now, my_command can sometimes return 1, but it should be an error, not an exception. It's kinda normal and I want to handle it. With promisify though, it becomes an Exception, so I tried to handle it this way:

let stdout, stderr: string;
try {
  const { stdout: execStdout, stderr: execStderr } = await execPromise(`my_command ${param}`);
  stdout = execStdout;
  stderr = execStderr;
} catch (e: unknown) {
  // ???
}

Here's what I tried for exception handling:

if (e instanceof ExecException) {}

but it fails with 'ExecException' only refers to a type, but is being used as a value here.

I also tried:

if ("stdout" in e) {}

because I want to retrieve stdout from the error but it fails with Object is of type 'unknown'..

I then tried to force a type assertion with:

e as ExecException

It kinda works but:

  • it's risky
  • I noticed ExecException doesn't have the stdout/stderr fields that it should have, so I still can't get them in case of error, which makes no sense...

So I'm a bit stuck on what I should do. Could someone help me?



Solution 1:[1]

You can define a Type Guard:

function isStdError(err: any): err is { stderr: string } {
    return !!err.stderr
}

Then in your code:

try {
    await exec(`my_command`)
} catch (e) {
    if (isStdError(e)) {
        console.log(e.stderr)
    } else {
        throw e
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 xonya