> Как реализовать функцию getProperty с типизацией в TypeScript, которая возвращает значение по ключу объекта? (TypeScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: Иннотех, КИТМЕД, IT-One, RecruitTech, Altenar
Стек: TypeScript
> Пример ответа
Короткий ответ
Для реализации getProperty с типизацией используйте дженерики и keyof: function getProperty<T, K extends keyof T>(obj: T, key: K): T[K]. Это гарантирует, что ключ существует в объекте, а возвращаемый тип соответствует типу значения по этому ключу. Для безопасной работы с опциональными или вложенными полями можно добавить проверки и использовать Partial или Record.
Подробное объяснение
Типизация getProperty строится на двух ключевых механизмах TypeScript: дженериках и операторе keyof. Дженерик T представляет тип объекта, а K extends keyof T ограничивает второй параметр только существующими ключами объекта. Возвращаемый тип T[K] - это lookup type, который выводит точный тип значения по указанному ключу.
Без такой типизации функция могла бы принимать любую строку в качестве ключа, что приводит к ошибкам времени выполнения. TypeScript в данном случае обеспечивает compile-time проверку: если ключ не существует в объекте, код не скомпилируется.
Для edge cases, например, когда объект может быть null или undefined, стоит добавить проверки внутри функции. Для работы с вложенными объектами можно создать рекурсивную типизацию с использованием conditional types.
На практике
В реальных проектах getProperty часто используется при работе с API-ответами, где структура данных известна, но может меняться. Типизация помогает избежать ошибок при рефакторинге: если поле переименовали или удалили, TypeScript укажет на все места использования.
Для сложных случаев, когда ключ может быть динамическим (например, из массива), используйте keyof typeof или as const для сужения типа. Для опциональных полей применяйте Partial<T> или T[K] | undefined в возвращаемом типе.
Пример кода
TYPESCRIPT// Базовая реализацияfunction getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {return obj[key];}// Пример использованияinterface User {id: number;name: string;email?: string;}const user: User = { id: 1, name: 'Alice' };const name = getProperty(user, 'name'); // stringconst id = getProperty(user, 'id'); // number// const invalid = getProperty(user, 'age'); // Ошибка компиляции// С проверкой на null/undefinedfunction getPropertySafe<T, K extends keyof T>(obj: T | null | undefined,key: K): T[K] | undefined {return obj?.[key];}// Для вложенных объектовtype NestedKey<T, K extends keyof T> = T[K] extends object? keyof T[K]: never;
Как отвечать на собеседовании
Начните с простого решения через дженерики и keyof, затем объясните, зачем это нужно: безопасность типов, автокомплит в IDE, защита от опечаток. Покажите, как TypeScript выводит точный тип возвращаемого значения. Упомяните, что для динамических ключей (например, из Object.keys) нужны дополнительные проверки, так как TypeScript не может гарантировать существование ключа в runtime.
Если собеседник спросит про сложные случаи, расскажите про conditional types для вложенных объектов, про as const для сужения литеральных типов и про satisfies оператор в TypeScript 4.9+.
Что проверяет интервьюер
Интервьюер оценивает понимание:
- дженериков и их ограничений
- оператора
keyofи lookup types - разницы между compile-time и runtime проверками
- работы с опциональными и вложенными полями
- практического применения типизации в реальных проектах
Также проверяется способность объяснить trade-off между строгостью типов и гибкостью кода.
Типичные ошибки
- Использование
anyдля ключа или возвращаемого значения - убивает всю пользу от типизации - Игнорирование случая, когда объект может быть
nullилиundefined - Попытка использовать
Object.keys(obj)для динамического доступа - TypeScript не может вывести тип ключа - Забывание про
readonlyполя -keyofвключает их, но модификация может быть запрещена - Слишком сложная типизация для простых случаев - не стоит использовать conditional types там, где достаточно базового
keyof
> Похожие задачи по frontend
Можно ли создать константу с несуществующим типом в TypeScript?
Как типизировать функцию, работающую с массивом промисов с разными типами в TypeScript
Что такое utility types в TypeScript, например Partial и DeepPartial
Что такое enum в TypeScript
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью