我正在尝试为我附加到Array.prototype
的JavaScript函数编写Typescript定义文件。
/**
* 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
上施加约束?
如果没有,我如何定义一个将为每个数组选择的接口,并在数组适合递归定义时识别该接口?
答案 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();
另请参见