Как создать пустой типизированный массив в TypeScript?
Основной способ: аннотация типа при объявлении
Самый распространённый и правильный способ создать пустой типизированный массив в TypeScript — это явно указать тип массива при объявлении переменной. TypeScript выведет тип never[] из пустого литерала [], поэтому без аннотации вы не сможете ничего в него добавить.
Вот как это выглядит для разных сценариев:
// Простой массив строк
let names: string[] = [];
names.push('Alice'); // ✅ OK
// Альтернативный синтаксис с generic
let names2: Array<string> = [];
names2.push('Bob'); // ✅ OK
// Массив чисел
let scores: number[] = [];
scores.push(100);
// Массив с юнион-типом (строка или число)
let mixed: (string | number)[] = [];
mixed.push('hello');
mixed.push(42);
Работа с интерфейсами и объектами
Для сложных типов, таких как объекты, используйте интерфейс или type alias:
interface Todo {
id: number;
title: string;
completed: boolean;
}
// Пустой массив задач
let todos: Todo[] = [];
// Теперь можно добавлять объекты, соответствующие интерфейсу
todos.push({
id: 1,
title: 'Изучить TypeScript',
completed: false
});
// Если попытаться добавить неполный объект — TypeScript выдаст ошибку
todos.push({
id: 2,
title: 'Купить продукты'
// ❌ Ошибка: missing 'completed'
});
Вариант с явным указанием типа через as
Иногда (например, при работе с библиотеками или сложной инициализацией) можно использовать приведение типа:
let items = [] as string[];
items.push('test'); // ✅ OK
// Для интерфейсов
let todos2 = [] as Todo[];
todos2.push({ id: 1, title: 'Задача', completed: true });
Этот синтаксис короче, но будьте осторожны: as не проверяет, что массив действительно пуст — он просто "говорит" TypeScript'у, что массив будет такого типа.
Использование конструктора Array
Ещё один вариант — через generic конструктор:
let numbers = new Array<number>();
numbers.push(1, 2, 3);
let todos3 = new Array<Todo>();
todos3.push({ id: 1, title: 'Дело', completed: false });
Однако этот способ менее популярен, так как он создаёт объект через конструктор, что чуть менее производительно и менее читаемо для простых случаев.
Что выбрать?
- Для простых типов:
let arr: string[] = [];— самый читаемый вариант. - Для интерфейсов и сложных типов:
let arr: Todo[] = [];— явно и типобезопасно. - Если нужно сократить код:
let arr = [] as Todo[];— компактно, но может скрыть ошибки при невнимательности. - Для динамического создания:
new Array<Type>()— редко, но допустимо.
Главное правило: всегда указывайте тип пустого массива явно, иначе TypeScript выведет never[], и вы не сможете ничего в него добавить без ошибки компиляции.
Альтернативный подход: использование readonly и кортежей
Иногда нужно не просто создать пустой массив, а гарантировать, что он останется неизменным (например, для конфигураций или констант). В таких случаях полезен модификатор readonly:
// Неизменяемый пустой массив строк
const emptyReadonly: readonly string[] = [];
// emptyReadonly.push('test'); ❌ Ошибка: push не существует на readonly массиве
Также для пустых массивов с фиксированной длиной (кортежей) можно использовать:
// Пустой кортеж из двух элементов
let pair: [string, number] = ['hello', 42]; // не пустой, но можно так:
let emptyPair: [string, number] = [] as any; // ❌ Плохая практика
// Лучше для кортежей:
type OptionalPair = [string?, number?];
let maybePair: OptionalPair = []; // ✅ Пустой кортеж
Когда это полезно? Если вы пишете библиотеку или API, где массив должен быть пустым и не должен изменяться — readonly даёт дополнительную защиту на уровне типов.
Ещё один нюанс: при работе с дженериками (функции, возвращающие пустой массив) используйте:
function createEmptyArray<T>(): T[] {
return [];
}
const nums = createEmptyArray<number>(); // nums: number[]
nums.push(5);
Этот паттерн часто встречается в фабричных методах и помогает сохранить типобезопасность при создании пустых контейнеров.