T型锯齿状数组的类型定义及其数组原型扩展

时间:2018-11-20 02:55:37

标签: javascript typescript typescript-generics

我正在尝试为我附加到Array.prototype的JavaScript函数编写Typescript定义文件。

Array.js

/**
 * Flattens the array recursively.
 *
 * @example
 * [1, [2, 3]].flat() // => [1, 2, 3]
 *
 * @example
 * [[1, [2, 3], [4, [5]]], 6].flat() // => [1, 2, 3, 4, 5, 6]
 */
Array.prototype.flat = function () {
    return this.reduce((arr, val) => Array.isArray(val) ? arr.concat(val.flat()) : arr.concat(val), []);
}

flat()Array<T|S>S的{​​{1}}上工作,并返回Array<T|S>。也就是说,它具有递归定义,并且所有数组都适合该定义,因为Array<T>只会返回原始数组的副本。

我是TypeScript的新手,但我的理解是,为了获得TypeScript定义文件(即IntelliSense)的好处,方法定义必须在[1, 2, 3].flat()之内。如果是这种情况,是否可以对interface Array<T>的专用版本在T上施加约束?

如果没有,我如何定义一个将为每个数组选择的接口,并在数组适合递归定义时识别该接口?

1 个答案:

答案 0 :(得分:3)

这不是一个完整的答案,但确实可以为我们提供大部分帮助。这是in the TypeScript Playground

type JaggedArrayItem<T> = T | JaggedArray<T>;

interface JaggedArray<T> extends Array<JaggedArrayItem<T>> { }

type FlatArray<T> = T extends JaggedArrayItem<infer U> ? U[] : T;

interface Array<T> {
  flat(this: JaggedArray<T>): FlatArray<T>;
}

Array.prototype.flat = function () {
  return this.reduce(
    (arr, val) => Array.isArray(val)
      ? arr.concat(val.flat())
      : arr.concat(val),
    []);
};

// Test

const myRecursiveArray: JaggedArray<number> = [
  10,
  [9],
  [
    [8],
    [
      [7],
    ]
  ],
];

const flattened: number[] = myRecursiveArray.flat();    
const flattenedToo: (string | number)[] = [1, 'two'].flat();

另请参见