在TypeScript中展平数组的数组

8i9zcol2  于 2023-06-24  发布在  TypeScript
关注(0)|答案(9)|浏览(155)

我想将string[][]展平为string[]
在几十个SO答案中给出的建议是:[].concat(...arrays)
但这给了我这个错误:
“string[]”类型的参数不能赋给“ConcatArray”类型的参数。
属性“slice”的类型不兼容。
类型'(开始?:数量|未定义,结束?:数量|undefined)=> string[]'不能赋值给类型'(start?:数量|未定义,结束?:数量|undefined)=> never[]'。
类型“string[]”不能赋值给类型“never[]”。
类型“string”不能赋值给类型“never”。
我尝试过的另一种方法是:

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

它给出了类似的错误:
“string[]”类型的参数不能赋给“ConcatArray”类型的参数。
为什么它对每个人都有效,除了我?

krcsximq

krcsximq1#

试试这个:

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

f87krz0w2#

您可以使用flat()展平阵列

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

原木

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

更新
通过将类型更正为string[],还可以使用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])
ygya80vv

ygya80vv3#

下面是最简单的选择:

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

就像@Kokodoko的方法,但输入内联。

ql3eal8s

ql3eal8s4#

下面是一个通用的解决方案:

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

和一个深度/递归扩展:

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

function flattenDeep<T>(input: NestedArray<T>): T[] {
  return flatten(input.map(x => Array.isArray(x) ? flattenDeep(x) : [x]));
};

This answer对于深度扁平化可能更有效,我只是很高兴尝试写一些对我来说更优雅的东西。

nnvyjq4y

nnvyjq4y5#

.flat()也会给予类型错误。您可以使用泛型来解决这个问题

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

不管怎样,你说了算。只要知道你的类型声明是不正确的。

roejwanj

roejwanj6#

密码

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

应该工作。我猜是tsconfig中的错误配置导致了这个错误。确保tsconfig的lib数组中至少有es2015(更好的是es2018)。要使新的flat如kokodoko所示工作,请确保还添加了esnext

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

kuarbcqp7#

我相信你有严格的NullCheck:真的
没有上下文类型的空数组([] in []. concat(arg))在strictNullChecks下被推断为never []。并且never不能从任何其他类型赋值。
([]concat(foo);应该可以

xxhby3vn

xxhby3vn8#

对于更深嵌套的数组,例如:[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;
  }, []);
};

用途:

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

rqenqsqc9#

来自Steven的答案在我的jest测试中有效,但在我的实际angular 15应用程序中无效,因为我无法弄清楚一个约束错误。稍微修改为常规递归函数,以保持Typescript安静:

import { Injectable} from '@angular/core';

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

export class ArrayHelper {
 
  public static flatten = <T>(input: NestedArray<T>, res: T[] = []): T[] => {
    input.forEach((el: T | NestedArray<T>) => {
      if (Array.isArray(el)) {
        ArrayHelper.flatten(el, res);
      } else {
        res.push(el);
      }
    });

    return res;
  };
}

示例测试:

describe('flattening', () => {
      it('pass through', () => {
        expect(ArrayHelper.flatten(['hi', 'there'])).toHaveLength(2);
      });

      it('2 level', () => {
        expect(ArrayHelper.flatten(['hi', 'there', ['that', 'is', 'all', 'folks']])).toHaveLength(6);
      });

      it('as per SO', () => {
        expect(ArrayHelper.flatten([1, 2, 3, [4, [5, [6, [7]]]]])).toHaveLength(7);
      });

      
    });

相关问题