Array<Type> VS Type[] в TypeScript: в чем разница и что выбрать?
Краткий ответ: синтаксический сахар vs обобщенный тип
На самом деле, Type[] и Array<Type> в TypeScript — это полностью эквивалентные способы объявления массива. Разница исключительно синтаксическая. Компилятор TypeScript обрабатывает их одинаково, и на выходе получается один и тот же JavaScript-код.
Детальное объяснение
Type[] — это сокращенная форма (синтаксический сахар), которая была введена для удобства и читаемости. Она интуитивно понятна разработчикам, пришедшим из других языков (C#, Java). Array<Type> — это полная форма с использованием обобщенного типа (generic). Оба варианта транслируются в один и тот же тип.
// Оба варианта идентичны
let a: number[] = [1, 2, 3];
let b: Array<number> = [1, 2, 3];
// TypeScript считает их одинаковыми
a = b; // OK
b = a; // OK
Когда использовать какой вариант?
Type[]— предпочтительный вариант для простых случаев. Он короче, легче читается и рекомендуется официальным стилем (TSLint/ESLint rule:array-type).Array<Type>— полезен в сложных конструкциях, где синтаксис с квадратными скобками может быть неудобен или двусмысленен.
Сложные случаи
Рассмотрим примеры, где Array<Type> становится удобнее:
// Пример 1: Массив функций
// С Type[] это выглядит запутанно:
let funcs1: (() => void)[];
// С Array<Type> — понятнее:
let funcs2: Array<() => void>;
// Пример 2: Вложенные дженерики
// Promise<number[]> — массив чисел внутри промиса
let p1: Promise<number[]>;
// Array<Promise<number>> — массив промисов
let p2: Array<Promise<number>>;
// Пример 3: Union типы
// Массив строк или чисел:
let mixed1: (string | number)[];
let mixed2: Array<string | number>;
Производительность
Разницы в производительности нет. TypeScript — это надстройка над JavaScript, которая существует только на этапе компиляции. Оба синтаксиса генерируют идентичный JavaScript-код:
// TypeScript
let arr1: number[] = [1, 2, 3];
let arr2: Array<number> = [1, 2, 3];
// Скомпилированный JavaScript
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
Рекомендации
- Для простых типов (number, string, boolean, объекты) используйте
Type[]— это стандарт. - Для сложных типов (функции, вложенные дженерики, union/intersection типы) используйте
Array<Type>для лучшей читаемости. - Настройте линтер: правило
@typescript-eslint/array-typeс опцией"array-simple"будет требоватьType[]для простых случаев иArray<Type>для сложных.
Заключение
Выбирайте синтаксис, который делает код более читаемым в конкретном контексте. Оба варианта абсолютно равноправны с точки зрения TypeScript. Главное — придерживаться единого стиля в рамках проекта.
<<Дополнительный взгляд: ReadonlyArray и неизменяемые массивы
Стоит отметить, что существует еще один связанный синтаксис — ReadonlyArray<Type> и readonly Type[]. Здесь также есть разница, но уже более существенная.
// Эквивалентные объявления
let arr1: ReadonlyArray<number> = [1, 2, 3];
let arr2: readonly number[] = [1, 2, 3];
// Оба запрещают мутацию
arr1.push(4); // Ошибка!
arr2[0] = 5; // Ошибка!
readonly Type[] — это сокращенная форма, которая появилась в TypeScript 3.4. Она короче и читается естественнее. Однако есть важное отличие: ReadonlyArray<Type> — это отдельный тип, а readonly Type[] — модификатор для типа массива. Это может влиять на вывод типов в некоторых сложных сценариях.
Также существует Readonly<Array<Type>>, но это уже избыточно. На практике используйте readonly Type[] для простоты, если ваш проект поддерживает TypeScript 3.4+.
Еще один момент: при работе с кортежами (tuples) синтаксис с квадратными скобками является единственно возможным:
// Кортеж — это не массив!
let tuple: [string, number] = ['hello', 42];
// Array<string, number> — так нельзя!
Таким образом, выбор между Type[] и Array<Type> — это вопрос стиля и читаемости, но знание альтернатив (особенно readonly) поможет писать более безопасный код.