2

Trying to convert this function to typescript:

const runProcess = (...proc) => {
  const proc = child_process.spawn(...proc, {
    stdio: ["ignore", "pipe", "pipe"],
  });

Can it be done? In this particular case, procs can be either a single string or a 2-tuple (how to represent this in TS?) made up of a string and an array of strings.

1
  • Yes it can be done. Which type is child_process.spawn expecting? Commented Nov 5, 2020 at 5:12

1 Answer 1

4

For creating a tuple, you just put the types inside of the square brackets in the order that they appear. [string, string[]] is the type for a 2-tuple of a string and an array of strings (string[]).

Since we are spreading the arguments of runProcess and treating it like an array, we need to treat the other argument type - a single string - as a 1-tuple [string].

We say that our args proc is either one of these two tuples: [string] | [string, string[]]. Therefore we know that the first element in the args array is always a string and the second element is either string[] or undefined. In order to call child_process.spawn, we want to default to an empty array for the second argument if none is given.

That signature looks like:

const runProcess = (...proc: [string] | [string, string[]]) => {
    const [str, arr = []] = proc;
    const child = child_process.spawn(str, arr, {
        stdio: ["ignore", "pipe", "pipe"],
    });
}

But given that we are always dealing with exactly one or two arguments, I'm not sure that it really makes sense to spread the arguments as ...proc. Why not just have a required first argument and an optional second argument that defaults to an empty array?

const runProcess = (command: string, args: string[] = []) => {
    const proc = child_process.spawn(command, args, {
        stdio: ["ignore", "pipe", "pipe"],
    });
}

Playground Link

Edit: as suggested by @Aleksey L., you can pass the spawn args as individual string arguments rather than as an array.

const runProcess = (command: string, ...args: string[]) => {
    const proc = child_process.spawn(command, args, {
        stdio: ["ignore", "pipe", "pipe"],
    });
}

Playground Link

Sign up to request clarification or add additional context in comments.

8 Comments

Sure, this allows defining the varargs as an array, but expanding it with the spread operator does not placate typescript: TSError: ⨯ Unable to compile TypeScript: searchwidget_take2.ts:14:42 - error TS2556: Expected 1-3 arguments, but got 1 or more. The error highlight is on the options object. It's not really going through and checking and seeing that the options object is intended to get interpreted as options. This could be an issue with the node types.
Ok that's why I asked what spawn was expecting. Seems like it is expecting 1-3 arguments only, and the error is that the array can have infinitely many? If that's the case then we need to be more specific in defining the second argument so that is has a limited length rather than just any array of strings. Is that right?
@LindaPaiste you can import child_process from 'child_process'; in playground, it works
args could be defined as rest parameter, then default can be removed and args can be passed without defining the array on caller site typescriptlang.org/play?#code/…
@AlekseyL. I like that!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.