Как типизировать Map, Set и объекты-словари в TypeScript и когда выбрать Record?
Массивы и коллекции
Для коллекций ключ-значение в TypeScript есть три основных варианта.
const users = new Map<string, { name: string }>();
users.set('u1', { name: 'Ada' });
const seen = new Set<number>([1, 2, 3]);
const prices: Record<string, number> = { apple: 10, pear: 12 };
const byId: { [id: string]: string } = {};Когда что
Map<K, V>— ключи любого типа, порядок вставки, быстрые добавления и удаления, размер черезsize. Подходит для динамических данных.Set<T>— уникальные значения.Record<K, V>— обычный объект. ЕслиK— объединение литералов, TypeScript потребует все ключи.
type Role = 'admin' | 'user';
const labels: Record<Role, string> = { admin: 'Админ', user: 'Пользователь' };Ловушка индексных сигнатур
prices['kiwi'] имеет тип number, хотя ключа может не быть. Включите noUncheckedIndexedAccess или используйте Map, чтобы получить V | undefined.
Для частичного словаря: Partial<Record<Role, string>>.
Коротко для собеседования
Map<K, V> подходит для произвольных ключей и частых изменений, Set<T> для уникальных значений, Record<K, V> для объекта с известным набором ключей. Включите noUncheckedIndexedAccess, чтобы чтение по ключу давало V | undefined.