ПрограммированиеFullstack разработчик

Каким образом работают Indexed Access Types (тип доступ по индексу, like T[K])? Когда их применять, как избежать ошибок при изменении структуры типа, и какова их роль в сложных объектах?

Проходите собеседования с ИИ помощником Hintsage

Ответ

Indexed Access Types (или типы доступ по индексу) позволяют ссылаться на тип конкретного свойства объекта или любого ключа через синтаксис T[K]. Это мощный инструмент для создания гибких и типобезопасных абстракций.

Пример:
type Person = { name: string; age: number; }; type NameType = Person['name']; // string type AgeOrName = Person['age' | 'name']; // number | string

Используется для написания универсальных типов и функций:

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; // корретная типизация возврата } const user = { email: 'a@a.ru', id: 1 }; let id = getProperty(user, 'id'); // id: number

Для чего:

  • Для создания типов-конструкторов (например, вытаскивания типа значения по ключу из сложных вложенных структур).
  • Строительство сопутствующих типов (Record, Pick и др.)

Нюансы:

  • При изменении исходного типа (Person) меняется и результат доступа по индексу, и это может внезапно повлиять на байндинг во всех местах!
  • TS не отлавливает ситуацию, если ключ не существует: Person['salary'] — ошибка на этапе компиляции.

Вопрос с подвохом

Вопрос: Какой тип получится у выражения type Foo = {a: number, b: string}["a" | "b" | "c"]?

Ответ: Этот пример вызовет ошибку компиляции, потому что 'c' не является ключом в типе, к которому осуществляется доступ. TypeScript выдаст ошибку:

Type '"c"' does not satisfy the constraint '"a" | "b"'.

Примеры реальных ошибок из-за незнания тонкостей темы.


История

В проекте динамически генерировались формы на основе типов. После добавления нового поля в основной тип не обновили места с индексацией по ключам, в результате некоторые свойства не попадали в форму, хотя на типовом уровне ожидался полный маппинг. Ошибка проявлялась только в runtime, а не на этапе разработки.


История

В библиотеке для валидации данных был использован индексируемый доступ через типы, но при миграции кода переместили один из ключей из объекта в родителя. Старый индексируемый тип приводил к ошибке компиляции, однако ошибка возникала только после пересборки из-за кэша в CI, и до этого жила на staging несколько недель.


История

Ошибочно полагали, что с помощью Indexed Access Types можно обращаться к любому ключу, даже если он не перечислен явно, что привело к неверной генерации автотестов для динамических свойств. В результате тесты не покрывали часть возможных сценариев, т.к. компилятор выбрасывал эти случаи как невалидные.