Типографские рекурсивные типы для массива массива

#typescript

Вопрос:

Я хочу описать некоторые данные, как если бы значение в массиве могло быть другим массивом чисел, это делается бесконечно, поэтому типы должны быть рекурсивными.

Со следующим кодом я получаю сообщение об ошибке

Type 'number' is not assignable to type 'Data'

 type Data = ReadonlyArray<number> | Data[];
const data: Data = [1, 2, 3, [4, 5, [6, 7]]];

 

Как это исправить, используя последнюю версию машинописного текста?

Ответ №1:

Typescript очень по-разному трактует типы объединений массива и объединения массива. Что — то вроде [1, 2, 3, [4, 5]] на самом деле имеет тип (number | number[])[] , которому нельзя присвоить number[] | number[][] .

Это означает, что вам нужен массив союзов, в котором союз может ссылаться на себя по кругу.

 type Data = readonly (number | Data)[];
 

Выше будет объявлен массив рекурсивного атома только для чтения, number . Теперь вы сможете назначить [1, 2, 3, [4, 5, [6, 7]]]

Попробуйте это на игровой площадке

Комментарии:

1. а как насчет этого type Data = ReadonlyArray<number | Data>; ? Что СЛУЧИЛОСЬ?

2. в чем разница между readonly и ReadonlyArray здесь? они должны быть эквивалентны, нет?

3. @Radex readonly number[] — это то же ReadonlyArray<number> readonly самое, что-поскольку ключевое слово просто более общее, вы можете использовать ReadonlyArray<number | Data> его просто отлично.

Ответ №2:

 type E = number

type ListOfE = E[]

type NestedListOfE = (E | NestedListOfE)[]

const a: E = 10
const b: ListOfE = [ 1, 2, 3 ]
const c: NestedListOfE = [ 1, 2, [ 3, [ 4, 5 ] ] ]
 

Примечание. использование рекурсивных типов доступно только начиная с TS 3.7.