Индексные сигнатуры и Record
Выбирайте между индексными сигнатурами и служебным типом Record
«Индексные сигнатуры и Record» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.
Два способа типизации словаря
TypeScript предлагает два распространённых способа описать словарь: сигнатуру индекса, например { [k: string]: V }, и встроенный вспомогательный тип Record<K, V>. Они во многом совпадают, но выглядят по-разному.
Вспомогательный тип Record
Record<K, V> создаёт тип объекта, ключами которого являются K, а значениями — V. Если в качестве ключа используется string, результат эквивалентен строковой сигнатуре индекса.
type Scores = Record<string, number>
const game: Scores = { alice: 10, bob: 7 }
console.log(game.alice)Эквивалент сигнатуры индекса
Эти два типа описывают одну и ту же структуру. Record<string, number> и { [key: string]: number } взаимозаменяемы для произвольных строковых ключей.
type A = Record<string, number>
type B = { [key: string]: number }
const a: A = { x: 1 }
const b: B = a // assignable both ways
console.log(b.x)Record с объединением литеральных ключей
Настоящая сила Record проявляется с конечным объединением ключей-литералов. Он создаёт объект, в котором каждый перечисленный ключ является обязательным, — то, что сигнатура индекса выразить не может.
type Role = "admin" | "editor" | "viewer"
type Perms = Record<Role, boolean>
const p: Perms = { admin: true, editor: true, viewer: false }
console.log(p.admin)Отсутствующие ключи обнаруживаются
Поскольку каждый литеральный ключ обязателен, пропуск одного приводит к ошибке компиляции. Это сильная гарантия, которую сигнатуры индекса просто не могут предоставить.
type Role = "admin" | "editor" | "viewer"
// const bad: Record<Role, boolean> = { admin: true, editor: true }
// Error: property viewer is missingСигнатура индекса допускает любой ключ
В отличие от неё, сигнатура индекса допускает открытый набор ключей. Можно добавлять ключи, которые нигде ранее не упоминались, и наличие ни одного ключа не является обязательным.
type Open = { [key: string]: number }
const o: Open = {} // no keys required
o.anything = 1 // any key allowed
console.log(o.anything)Для конечных наборов ключей выбирайте Record
Когда ключи образуют известный конечный набор, Record с объединением литералов понятнее и безопаснее. Он точно документирует существующие ключи и требует указать их все.
type Direction = "north" | "south" | "east" | "west"
type Moves = Record<Direction, number>
const m: Moves = { north: 1, south: 0, east: 2, west: 0 }
console.log(m.east)Для открытых наборов подходит любой вариант
Когда ключи не ограничены и обнаруживаются во время выполнения, подходят и Record<string, V>, и сигнатура индекса. Многие команды выбирают Record за краткость, а другие — сигнатуру за явность.
type Cache1 = Record<string, string>
type Cache2 = { [url: string]: string }
const c: Cache1 = {}
c["/home"] = "<html>"
console.log(c["/home"])Record — всего лишь отображаемый тип
Внутри Record<K, V> определён как отображаемый тип: { [P in K]: V }. Это объясняет, почему объединение литералов создаёт обязательные ключи, а string — сигнатуру индекса.
// lib definition (simplified):
// type Record<K extends string | number | symbol, V> = { [P in K]: V }
type Flags = Record<"a" | "b", boolean>
const f: Flags = { a: true, b: false }
console.log(f.a)Именованные ключи плюс универсальное правило
Сигнатура индекса может объединять универсальное правило для остальных ключей с фиксированными ключами в одном интерфейсе — это удобно, когда нужно и то и другое. Сам по себе Record не может так же удобно сочетать обязательные именованные ключи с открытым набором остальных.
interface Response {
status: number
[header: string]: number | string
}
const r: Response = { status: 200, "x-id": "abc" }
console.log(r.status)Практический выбор
Практическое правило: конечные известные ключи → Record<Union, V> для проверки полноты. Неограниченный набор ключей → подходит любой вариант. Нужны именованные ключи и универсальное правило для остальных → используйте сигнатуру индекса внутри интерфейса.
type Status = "ok" | "error"
type Messages = Record<Status, string>
const msg: Messages = { ok: "done", error: "failed" }
console.log(msg.ok)Быстрая проверка
Проверьте, насколько вы поняли разницу между Record и сигнатурами индекса.
Итоги
Record<string, V> эквивалентен строковой сигнатуре индекса, но Record с объединением литеральных ключей делает каждый перечисленный ключ обязательным и обнаруживает пропуски на этапе компиляции. Используйте Record<Union, V> для конечных известных ключей, любой вариант — для неограниченного набора ключей, а сигнатуру индекса — когда нужны именованные ключи и универсальное правило для остальных. Внутри Record является отображаемым типом { [P in K]: V }.
Изучай TypeScript с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 101
- Уроки
- 352
Часто задаваемые вопросы
Урок «Индексные сигнатуры и Record» бесплатный?
Да — полный текст урока «Индексные сигнатуры и Record» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.
Чему я научусь в уроке «Индексные сигнатуры и Record»?
Выбирайте между индексными сигнатурами и служебным типом Record Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать TypeScript Academy?
Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Индексные сигнатуры и Record»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке TypeScript Academy?
Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Определение индексных сигнатур
- Индексные сигнатуры строк и чисел
- Объединение известных и динамических ключей
- Индексные сигнатуры и Record