Использование keyof с Generics

Тренажер по TypeScript для пользователей с начальным уровнем подготовки.

Тренажер по TypeScript

При работе с дженериками (Generics) часто возникает задача ограничить типы так, чтобы они соответствовали ключам определенного объекта. Для этого используется оператор keyof в сочетании с ключевым словом extends.

Конструкция K extends keyof T гарантирует, что тип K может быть только одним из ключей типа T. Это незаменимо при написании безопасных функций для получения или изменения свойств объектов, таких как getProperty(obj, key), где TypeScript подскажет возможные ключи и запретит опечатки.

Здесь вы научитесь связывать дженерики с ключами объектов для повышения надежности кода.

Список тем

1. Выделение ограничения

id: 40718_ts_gen_keyof_highlight_01

В данном задании вам представлена сигнатура обобщенной функции на TypeScript. Разметьте выделенные фрагменты кода, указав для каждого, является ли он именем функции, объявлением generic-параметра, ключевым словом ограничения, оператором keyof, ссылкой на тип или именем параметра. Обратите внимание на часть, отвечающую за ограничение дженерика ключами объекта (использование 'extends keyof').

Кликните по каждому выделенному фрагменту и выберите для него подходящий тип из списка под текстом.
function {{getProperty~|~t1}}<{{T~|~t2}}, {{K~|~t3}} {{extends~|~t4}} {{keyof~|~t5}} {{T~|~t6}}>({{obj~|~t7}}: {{T~|~t8}}, {{key~|~t9}}: {{K~|~t10}}): {{T~|~t11}}[{{K~|~t12}}] {
    return obj[key];
}
Generic Parameter Declaration
Function Name
Parameter Name
Keyof Operator
Type Reference
Constraint Keyword
Сообщения
Проверить
Показать подсказку

2. Связывание типа и ключей

id: 40718_ts_gen_keyof_replace_02

Дополните объявление функции getValue, чтобы второй параметр key был ограничен ключами первого параметра obj. Используйте ключевые слова для ограничения generic-параметра. Функция должна возвращать значение типа, соответствующего свойству объекта по переданному ключу. Заполните пропуски в коде, чтобы обеспечить типовую безопасность при обращении к свойствам объекта.

Заполните пропуски
// Функция getValue возвращает значение свойства объекта по заданному ключу.
// Второй аргумент должен быть ключом первого аргумента.
function getValue<T, K input1S input2S T>(obj: T, key: K): T[K] {
    return obj[key];
}
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

3. Валидные ключи

id: 40718_ts_gen_keyof_click_target_03

В данном фрагменте кода TypeScript определён интерфейс `Car` и функция `getProperty`, которая принимает объект и ключ. Внимательно изучите вызовы функции `getProperty`. Ваша задача — отметить все строковые литералы, которые являются валидными ключами интерфейса `Car` (то есть существуют в этом интерфейсе). Не отмечайте строки, которые не являются ключами `Car`, даже если они встречаются в вызовах функции. Также не отмечайте никакие другие части кода (например, имена переменных, значения свойств и т.д.).

Кликните по всем фрагментам, которые подходят под условие задания.
interface Car {
  brand: string;
  model: string;
  year: number;
}

function getProperty<T, K extends keyof T>(obj: T, key: K) {
  return obj[key];
}

const myCar: Car = { brand: 'Toyota', model: 'Corolla', year: 2020 };

// Примеры вызовов функции
getProperty(myCar, {{"brand"~|~t1}});
getProperty(myCar, {{"model"~|~t2}});
getProperty(myCar, {{"year"~|~t3}});
getProperty(myCar, {{"color"~|~t4}});
getProperty(myCar, {{"price"~|~t5}});
Сообщения
Проверить
Показать подсказку

4. Типизация аргументов

id: 40718_ts_gen_keyof_select_04

В этом задании вам нужно выбрать правильную типизацию для аргумента 'key' в функции обновления поля объекта. Функция updateField принимает объект типа T, ключ и новое значение, затем обновляет соответствующее поле. Из предложенных вариантов выберите тип, который гарантирует, что ключ будет существующим свойством объекта типа T, обеспечивая типобезопасность при обращении к полям объекта.

Нужно правильно расставить в пропуски предложенные варианты
function updateField<T>(obj: T, key: input1S, value: T[keyof T]): void {
  obj[key] = value;
}

interface User {
  name: string;
  age: number;
}

const user: User = { name: "Alice", age: 30 };
updateField(user, "name", "Bob");
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

5. Функция getProperty

id: 40718_ts_gen_keyof_build_05

Из предложенных строк соберите корректную сигнатуру функции getProperty на TypeScript, которая использует Generics с ограничением keyof для безопасного доступа к свойствам объекта. Функция должна принимать объект и ключ, который гарантированно является ключом этого объекта, и возвращать значение соответствующего типа. В решении должны использоваться только необходимые строки — лишние строки (decoys) включать не нужно.

Перетяните в правильном порядке строки из одного блока в другой
function getProperty
<T, K extends keyof T>
(obj: T, key: K)
: T[K]
function setProperty
<T, K extends keyof T>(obj: T, key: K, value: T[K]): void
return obj[key];
}
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

6. Исправление ограничения

id: 40718_ts_gen_keyof_error_06

В этом фрагменте кода TypeScript, использующем дженерики и keyof, допущена синтаксическая ошибка. В объявлении функции getProperty пропущено ключевое слово 'extends' между именем дженерика и 'keyof T', из-за чего компилятор не может правильно интерпретировать ограничение типа. Исправьте строку с ошибкой, чтобы функция могла корректно получать значение свойства объекта по его ключу.

Найдите ошибку и исправьте
function getProperty<T, K keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}
 
const person = { name: 'Alice', age: 30 };
const nameValue = getProperty(person, 'name'); // Ожидается 'Alice'
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

7. Результат ограничения

id: 40718_ts_gen_keyof_predict_07

Рассмотрите приведенный код TypeScript, который определяет интерфейс Product и обобщенную функцию getValue с ограничением типа для параметра key. На основе понимания оператора keyof и ограничений дженериков, выберите верное утверждение о том, какие значения могут быть переданы в качестве аргумента key при вызове функции getValue для объекта laptop.

Выберите правильный вариант ответа
interface Product {
    id: number;
    name: string;
    price: number;
}

function getValue<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

const laptop: Product = { id: 1, name: "Laptop", price: 999 };
Сообщения
Проверить
Показать подсказку

TypeScript: компиляция и запуск

id: 40718_compiler

Этот пример показывает, как использовать keyof с Generics для создания безопасных функций доступа к свойствам объектов. Вы можете изменять объект user, добавлять новые свойства, пробовать разные ключи в вызовах функций. Попробуйте передать несуществующий ключ — TypeScript сразу покажет ошибку! Экспериментируйте: создайте свои объекты с разными типами, добавьте новые функции для работы с ними.

TS
Запустить тренажёр (TypeScript)
НайтиКурс.Ру