Search code examples
javascriptarraystypescriptone-liner

Looking for a one-liner to convert x or x[] into x[]


I'm looking for short and valid plain TypeScript one-liner that could replace the following function:

function arrayOrMemberToArray<T>(input: T | T[]): T[] {
  if(Arrary.isArray(input)) return input
  return [input]
}

Cramming the above logic into a one-line ternary operator is quite messy and hard to follow when chained with other operations:

const y = (Array.isArray(input) ? input : [input]).map(() => { /* ... */}) // Too messy

Array.concat works fine in browser console, but TS doesn't allow it:

const x: number | number[] = 0
const y = [].concat(x)
Error:(27, 21) TS2769: No overload matches this call.
  Overload 1 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
    Argument of type 'number' is not assignable to parameter of type 'ConcatArray<never>'.
  Overload 2 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
    Argument of type 'number' is not assignable to parameter of type 'ConcatArray<never>'.

Solution

  • The concat solution doesn't typecheck because of the empty array literal. You'd need to write

    const arr = ([] as number[]).concat(input);
    

    Alternatively, you can use flat:

    const arr = [input].flat();
    

    This would not only be shorter but also preferable because it doesn't rely on the concat-spreadable property of the input but actually checks for arrays.