Індексований тип доступу - отримати тип властивості іншого типу тим самим синтаксисом, що й доступ до поля об'єкта:
interface Order {
id: number;
status: 'new' | 'paid' | 'shipped';
customer: { name: string; email: string };
items: { sku: string; qty: number }[];
}
type OrderStatus = Order['status']; // 'new' | 'paid' | 'shipped'
type Customer = Order['customer']; // { name: string; email: string }
type CustomerEmail = Order['customer']['email']; // string
type IdOrStatus = Order['id' | 'status']; // number | 'new' | 'paid' | 'shipped'
T[number] - тип елемента масиву:
type OrderItem = Order['items'][number]; // { sku: string; qty: number }
const SIZES = ['sm', 'md', 'lg'] as const;
type Size = (typeof SIZES)[number]; // 'sm' | 'md' | 'lg'
number як індекс означає «будь-який числовий індекс» - тобто тип будь-якого елемента. Для кортежів - об'єднання типів усіх елементів.
Навіщо це:
- не дублювати описи: тип статусу береться з
Order, і якщо статуси зміняться, похідні типи оновляться; - типи для частин відповіді API: згенерований тип відповіді великий, а компоненту потрібна одна вкладена частина -
ApiResponse['data']['items'][number]; - поєднання з
keyof:T[keyof T]- об'єднання типів усіх значень об'єкта.
const LABELS = { draft: 'Чернетка', published: 'Опубліковано' } as const;
type Label = (typeof LABELS)[keyof typeof LABELS]; // 'Чернетка' | 'Опубліковано'
Обмеження:
- індекс - тип, а не значення:
Order[key], деkey- змінна, не працює. ПотрібноOrder[typeof key]або параметр типу; - лише існуючі ключі:
Order['phone']- помилка; - необов'язкове поле дає тип з
undefined: дляemail?: string-string | undefined. Прибрати -NonNullable<User['email']>.
Різниця з доступом під час виконання: noUncheckedIndexedAccess додає | undefined до доступу до масиву за індексом у коді, але T[number] у типах повертає тип елемента без undefined.