Преобразовать строковый параметр в массив из одного элемента

Я написал функцию, которая должна поддерживать два типа names параметров для списка значений. Внутренне это имеет дело с параметром как массив.

Одно имя задается в виде строки, а кратные имена - в виде массива строк.

// simplified example
let doSome =  names => names.map(name => name.toUpperCase())

names(['Bart', 'Lisa'])
// [ 'BART', 'LISA' ]
names('Homer')
// TypeError: names.map is not a function

Я нашел решение, используя Array.of() в сочетании с flatten() который нуждается в некоторой конфигурации babel.

doSome = names => Array.of(names).flatten().map(name => name.toUpperCase());

Есть ли в JavaScript идиоматический способ получить массив без проверки типа?

Ответ 1

Вы можете использовать Array.concat(), так как concat принимает как массивы, так и не массивы:

const names = (v) => [].concat(v).map(name => name.toUpperCase())

console.log(names(['Bart', 'Lisa'])) // [ 'BART', 'LISA' ]
console.log(names('Homer')) // ['HOMER']

Ответ 2

Возможно, вы не сможете реализовать его таким образом, если у вас уже есть код, зависящий от этой функции. Тем не менее, возможно, было бы чище позволить вашей функции принимать переменное число аргументов с параметрами покоя.

Это означает, что вы можете вызывать функцию как names('Homer') или names('Bart', 'Lisa'):

function names(...args){
  return args.map(name => name.toUpperCase());
}

console.log(names('Bart', 'Lisa')); // [ 'BART', 'LISA' ]
console.log(names('Homer')); // ['HOMER']

Ответ 3

Почему бы просто не проверить, является ли ввод массивом или не используется isArray()?

Я принял другое решение, используя этот подход, а также поместил элемент управления в map() чтобы он не завершился ошибкой, когда аргумент name является null или undefined.

const names = x => (Array.isArray(x) ? x : [x]).map(name => name && name.toUpperCase());

console.log(JSON.stringify( names(['Bart', 'Lisa']) ));
console.log(JSON.stringify( names('Homer') ));
console.log(JSON.stringify( names('') ));
console.log(JSON.stringify( names(null) ));
console.log(JSON.stringify( names([null]) ));
console.log(JSON.stringify( names([undefined, "Roger", "Bob", null]) ));

Ответ 4

Возможно, в этом случае поможет новый метод Array#flat (работает на самом деле только в Chrome и FF).

const names = unknown => [unknown].flat().map(name => name.toUpperCase())

console.log(names(['Bart', 'Lisa']));
console.log(names('Homer'));