В TypeScript массивы описываются двумя основными способами: тип[] и Array<тип>. Для массивов с элементами разного типа используются объединенные типы (union types) или кортежи (tuples), которые позволяют описывать фиксированный набор элементов разного типа и количества.
Объявления массивов:
let numbers: number[] = [1, 2, 3]; let strings: Array<string> = ['a', 'b', 'c'];
Массив с элементами разных типов:
let mixed: (string | number)[] = [1, 'a', 2];
Кортежи (tuples):
let tuple: [string, number, boolean] = ['hello', 42, true];
С кортежами удобнее работать, когда ожидается фиксированная структура (например, вернуть из функции сразу несколько разных по типу значений), а с массивами — когда количество и тип элементов может быть перемешано или неизвестно заранее.
Можно ли после определения кортежа с длиной N добавить к нему элементы с помощью push? Как это влияет на типизацию?
Ответ: Да, пушить в кортеж можно — компилятор разрешает это, хотя это нарушает предпосылку ограниченности корретжа по длине. Типы новых элементов будут приводиться к объединению всех возможных типов элементов кортежа:
let tuple: [number, string] = [42, 'foo']; tuple.push(true); // OK! tuple now: [number, string, boolean], но тип не обновился, а ошибки нет! console.log(tuple); // [42, 'foo', true]
Поэтому работу с кортежами и их изменяемость нужно контролировать вручную или делать их readonly.
История
Разработчик описал функцию, возвращающую кортеж [number, string], но затем начал добавлять к результату элементы через push. Это привело к рассинхронизации типов: последующий код ожидал ровно два элемента с определёнными типами, но получал массив переменной длины, из-за чего возникали рантайм-ошибки при распаковке значений и чтении по несуществующим индексам.
История
Для хранения массива значений разных типов был использован массив any[], считая это универсальным решением. В результате TypeScript перестал проверять правильность типов, и логика приложения начала "ломаться" из-за неправильных преобразований типов, которые не вызывали ошибок компиляции.
История
В проекте массив описывался либо через тип[], либо через Array<тип> — но в одних местах допускалась запись let arr: any[] (чтобы работать "с чем угодно"). Из-за этого появлялись неконтролируемые преобразования, функцию принимала любой массив, что приводило к runtime-ошибкам при попытке вызвать некорректные методы для элементов разных типов.