Typescript: как вводить переменные аргументы?

#typescript

#typescript

Вопрос:

Пытаюсь преобразовать эту функцию в typescript:

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

Можно ли это сделать? В этом конкретном случае procs может быть либо одной строкой, либо 2-кортежем (как представить это в TS?), состоящим из строки и массива строк.

Комментарии:

1. Да, это можно сделать. Какой тип child_process.spawn ожидается?

Ответ №1:

Для создания кортежа вы просто помещаете типы внутри квадратных скобок в том порядке, в котором они появляются. [string, string[]] это тип для 2-го кортежа a string и массива строк ( string[] ) .

Поскольку мы распределяем аргументы runProcess и обрабатываем их как массив, нам нужно обрабатывать другой тип аргумента — одну строку — как 1-кортеж [string] .

Мы говорим, что наши аргументы proc являются одним из этих двух кортежей : [string] | [string, string[]] . Поэтому мы знаем, что первым элементом в массиве args всегда является a string , а вторым элементом является либо string[] или undefined . Для вызова child_process.spawn мы хотим по умолчанию использовать пустой массив для второго аргумента, если он не задан.

Эта подпись выглядит так:

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

Но, учитывая, что мы всегда имеем дело ровно с одним или двумя аргументами, я не уверен, что действительно имеет смысл распространять аргументы как ...proc . Почему бы просто не иметь обязательный первый аргумент и необязательный второй аргумент, который по умолчанию равен пустому массиву?

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

Ссылка на игровую площадку

Редактировать: как предложил @Aleksey L., вы можете передавать порождение args как отдельные строковые аргументы, а не как массив.

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

Ссылка на игровую площадку

Комментарии:

1. Конечно, это позволяет определять переменные как массив, но расширение его с помощью оператора spread не успокаивает typescript: TSError: ⨯ Unable to compile TypeScript: searchwidget_take2.ts:14:42 - error TS2556: Expected 1-3 arguments, but got 1 or more. Выделение ошибки находится на объекте options . На самом деле это не проверка и проверка того, что объект options предназначен для интерпретации как options . Это может быть проблемой с типами узлов.

2. Хорошо, вот почему я спросил, чего spawn ожидать. Похоже, что он ожидает только 1-3 аргумента, и ошибка в том, что в массиве может быть бесконечно много? Если это так, то нам нужно быть более конкретными в определении второго аргумента, чтобы он имел ограниченную длину, а не просто любой массив строк. Это правильно?

3. @LindaPaiste вы можете import child_process from 'child_process'; на игровой площадке, это работает

4. args может быть определено как параметр rest, тогда значение по умолчанию может быть удалено, а аргументы могут быть переданы без определения массива на вызывающем сайте typescriptlang.org/play ? #code/ …

5. @AlekseyL. Мне это нравится!