简体   繁体   中英

Flatten array of arrays in TypeScript

I want to flatten string[][] into string[] .

The advice given in dozens of SO answers is: [].concat(...arrays) .

But that gives me this error:

Argument of type 'string[]' is not assignable to parameter of type 'ConcatArray'.
Types of property 'slice' are incompatible.
Type '(start?: number | undefined, end?: number | undefined) => string[]' is not assignable to type '(start?: number | undefined, end?: number | undefined) => never[]'.
Type 'string[]' is not assignable to type 'never[]'.
Type 'string' is not assignable to type 'never'.

Another way I tried is this:

let foo: string[][] = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]];
let bar = [].concat(...foo);

Which gives a similar error:

Argument of type 'string[]' is not assignable to parameter of type 'ConcatArray'.

Why does it work for everyone but me?

Try this:

 const a = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]] const result = a.reduce((accumulator, value) => accumulator.concat(value), []); console.log(result)

You can flatten the array with flat()

let foo: string[][] = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]];
let bar = foo.flat()

log

console.log(bar)   // a,b,c,a,b,c,a,b,c 

UPDATE

By correcting the type to string[] you can also use concat

let foo: string[][] = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]];
let bar : string[] = []
bar = bar.concat(foo[0], foo[1], foo[2])

Here's the simplest option:

let bar = ([] as string[]).concat(...foo);

Like @Kokodoko's approach but with the typings inline.

.flat() will also give the type error. You can use Generics to solve this

 let st : string[][] | Array<string> = [['a'] , ['b']] let bar = [].concat(...st); console.log(bar)

Either way, your call. Just know that your type declaration is not right.

Here's a generic solution:

function flatten<T>(arr: T[][]): T[] {
  return ([] as T[]).concat(...arr);
}

I believe you have strictNullCheck: true

An empty array with no contextual type ([] in [].concat(arg)) is inferred as never[] under strictNullChecks. and never is not assignable from any other type.

([] as any[]).concat(foo); should do the trick

The code

const res = [].concat(...foo);

should work. I guess it's a misconfiguration in tsconfig that causes that error for you. Make sure that there is at least es2015 (better es2018 ) in your tsconfig's lib array. To make the new flat work as shown by kokodoko, make sure to also add esnext

"lib": [
  "es2018",
  "dom",
  "esnext"
]

For much more deeply nested array of arrays such as: [1, 2, 3, [4, [5, [6, [7]]]]]

type NestedArray<T> = Array<NestedArray<T> | T>;

const flatten = <T>(input: NestedArray<T>, acc: T[] = []): T[] => {
  return input.reduce((_: T[], current) => {
    if (Array.isArray(current)) return flatten(current, acc);  
    acc.push(current);
    return acc;
  }, []);
};

Usage:

console.log(flatten([1, 2, 3, [4, [5, [6, [7]]]]]));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM