> Как типизировать объект с разными ключами и значениями в TypeScript? (TypeScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Инрэко, КИТМЕД

Стек: TypeScript

> Пример ответа

Короткий ответ

Для типизации объекта с разными ключами и значениями в TypeScript используют index signature: { [key: string]: number }. Если ключи заранее известны, применяют mapped types: { [K in 'a' | 'b']: string }. Для смешанных типов значений - union в index signature или Record с discriminated union. При необходимости точной типизации каждого ключа - interface с конкретными полями.

Подробное объяснение

TypeScript предоставляет несколько подходов в зависимости от сценария:

  1. Index signature - когда ключи неизвестны заранее, но все значения одного типа:

    TYPESCRIPT
    interface StringMap {
    [key: string]: string;
    }
  2. Mapped types - когда ключи известны, а значения могут быть разными:

    TYPESCRIPT
    type Config = {
    [K in 'host' | 'port' | 'ssl']: K extends 'port' ? number : string;
    };
  3. Record<K, V> - утилитарный тип для однотипных значений:

    TYPESCRIPT
    type UserRoles = Record<'admin' | 'user', string>;
  4. Union в значении - если значения разных типов:

    TYPESCRIPT
    interface MixedMap {
    [key: string]: string | number | boolean;
    }
  5. Discriminated union - для строгой типизации каждого ключа:

    TYPESCRIPT
    type Schema = {
    name: string;
    age: number;
    active: boolean;
    };

Важно: index signature с string ключом конфликтует с конкретными полями другого типа - нужно использовать intersection или mapped types.

На практике

В реальных проектах чаще всего встречаются:

  • API responses - используют Record<string, unknown> с последующей валидацией (zod, io-ts)
  • Configuration objects - конкретные интерфейсы с optional полями
  • Dynamic forms - mapped types с conditional types для разных типов полей
  • Event maps - Record<EventName, Handler> с discriminated union

Для сложных случаев применяют generic constraints:

TYPESCRIPT
function createStore<T extends Record<string, unknown>>(initial: T) {
// ...
}

Пример кода

TYPESCRIPT
// Index signature для динамических ключей
interface Dictionary<T> {
[key: string]: T;
}
const dict: Dictionary<number> = { a: 1, b: 2 };
// Mapped type для известных ключей с разными типами
type FormState = {
[K in 'email' | 'password' | 'remember']:
K extends 'remember' ? boolean : string;
};
// Record с union типом
type StatusMap = Record<'pending' | 'success' | 'error', string>;
// Смешанный объект с конкретными полями
interface UserProfile {
id: number;
name: string;
metadata: Record<string, unknown>;
tags: string[];
}
// Generic helper для типизации динамических объектов
type TypedObject<K extends string, V> = {
[P in K]: V;
};

Как отвечать на собеседовании

Начни с index signature как базового решения, затем упомяни mapped types для известных ключей. Объясни trade-off между гибкостью и типобезопасностью. Приведи пример из реального проекта - например, типизацию конфига или ответа API. Покажи понимание ограничений: index signature не работает с конкретными полями другого типа. Упомяни альтернативы вроде Partial, Pick, Omit для сложных сценариев.

Что проверяет интервьюер

  • Понимание разницы между index signature и mapped types
  • Умение выбирать правильный подход под задачу
  • Знание ограничений TypeScript (например, конфликт index signature с конкретными полями)
  • Способность типизировать реальные сценарии (API, конфиги, формы)
  • Понимание trade-off между строгостью типов и гибкостью

Типичные ошибки

  • Использование any вместо unknown для неизвестных значений
  • Попытка добавить конкретное поле с другим типом в объект с index signature
  • Игнорирование readonly для иммутабельных объектов
  • Злоупотребление Record<string, any> вместо более точных типов
  • Неправильное использование conditional types в mapped types
  • Забывание про keyof для динамической работы с ключами

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью