Определение типа для зубчатого массива типа T и расширения его прототипа - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь написать файл определения Typescript для функции JavaScript, которую я прикрепил к Array.prototype.

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 равно Array<T|S> и возвращает Array<T>.То есть он имеет рекурсивное определение, и все массивы соответствуют определению, так как [1, 2, 3].flat() просто возвратит копию исходного массива.

Я новичок в TypeScript, но я понимаю, что по порядкуЧтобы получить преимущества файла определения TypeScript (а именно IntelliSense), определение метода должно быть в пределах interface Array<T>.Если это так, есть ли способ наложить ограничение на T для специализированной версии Array<T>?

Если нет, как я могу определить интерфейс, который будет выбран для каждого массива И будет распознавать, когда массив соответствует рекурсивному определению?

1 Ответ

0 голосов
/ 20 ноября 2018

Это не полный ответ, но он дает нам большую часть пути.Вот оно на игровой площадке TypeScript .

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();

См. Также

...