简体   繁体   English

打字稿,如何为数组编写类型化的展平方法

[英]Typescript, How to write a typed flatten method for array

I am trying to write in typescript something similar to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat我正在尝试在打字稿中编写类似于https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat 的内容

However, I want to be able to flatten nested list of arbitrary depth;但是,我希望能够展平任意深度的嵌套列表; and also I want to restrict all non array elements to a single type.而且我想将所有非数组元素限制为单一类型。

Something like:就像是:

interface NestedList<T> extends Array<T | NestedList<T>> {}

I have got this so far:到目前为止我已经得到了这个:

export const flat = <T>(ls: NestedList<T>): T[] => {
   const reducer = (acc: T[], it: T | NestedList<T>): T[] => acc.concat(
      Array.isArray(it) ? it.reduce(reducer, []) : it
   );

   return ls.reduce(reducer, []);
};

However, the type inference does not seem to be working但是,类型推断似乎不起作用

   it('works with type inference', () => {
      interface Foo<T> { v: T; }

      const data: { [_: string]: { [_: string]: Foo<number> } } = {
         bar: { x: { v: 1 } },
         moo: { y: { v: 2 }, z: { v: 3 } }
      };

      const nested: Foo<number>[][] = Object.values(data).map(val => Object.values(val));
      const list2: Foo<number>[] = flat(nested);
      expect(list2).toEqual([{ v: 1 }, { v: 2 }, { v: 3 }]);
   });

It receives type error on this line:它在这一行收到类型错误:

const list2: Foo<number>[] = flat(nested);

Error:错误:

Type '(Foo<number>[] | ConcatArray<Foo<number>[]>)[]' is not assignable to type 'Foo<number>[]'.
  Type 'Foo<number>[] | ConcatArray<Foo<number>[]>' is not assignable to type 'Foo<number>'.
    Property 'v' is missing in type 'Foo<number>[]' but required in type 'Foo<number>'

What I am missing here?我在这里缺少什么? Any help is appreciated.任何帮助表示赞赏。

I stumbled on the same problem as you.我偶然发现了和你一样的问题。 This is the solution I came up with:这是我想出的解决方案:

function flat<U>(arr: U[][]): U[] {
    if ((arr as unknown as U[]).every((val) => !Array.isArray(val))) {
        return (arr as unknown as U[]).slice();
    }
    return arr
        .reduce((acc, val) => acc
            .concat(Array.isArray(val) ? flat((val as unknown as U[][])) : val), []);
}

console.log(flat([[1,2],[[[3]]],4])

Hope it helps you :)希望对你有帮助:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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