Avatar ·

Array<Type> VS Type[] в TypeScript: в чем разница и что выбрать?

Всем привет! Я только начал изучать TypeScript и столкнулся с непонятной ситуацией. При объявлении массивов я вижу два разных синтаксиса: ```typescript const numbers: number[] = [1, 2, 3]; const strings: Array = ['a', 'b', 'c']; ``` Оба варианта работают и, кажется, делают одно и то же. Но я не понимаю, есть ли между ними разница? Когда какой вариант использовать? Я попробовал оба способа в своем проекте: ```typescript // Вариант 1 let list1: number[] = [1, 2, 3]; // Вариант 2 let list2: Array = [1, 2, 3]; // Оба компилируются без ошибок ``` Мне кажется, что `Array` выглядит более "типизированным", а `Type[]` — короче. Но может быть есть какие-то подводные камни или случаи, когда один вариант не работает, а другой — да? Особенно меня интересует: 1. Есть ли разница в производительности? 2. Можно ли их смешивать? 3. Что говорят гайдлайны TypeScript? 4. Какой вариант предпочтительнее для сложных типов, например, когда массив содержит объекты или другие массивы? Буду благодарен за развернутый ответ с примерами! Заранее спасибо! <<>>

Краткий ответ: синтаксический сахар 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) поможет писать более безопасный код.