in operator narrowing

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

Тренажер по TypeScript

При работе с Union-типами часто возникает необходимость точно определить, с каким именно вариантом объекта мы работаем в данный момент. Для этого в TypeScript существуют Type Guards (защитники типа).

Оператор in — это один из самых элегантных способов сужения типов (narrowing). Он проверяет наличие определенного ключа (свойства) в объекте во время выполнения программы.

Пример: if ('fly' in animal) { ... }. Внутри этого блока TypeScript будет точно знать, что переменная animal обладает свойством fly, и позволит обращаться к нему безопасно. Это незаменимый инструмент при обработке ответов API или сложной логики состояний.

В этом блоке заданий вы научитесь:

  • Использовать оператор in для проверки свойств.
  • Различать интерфейсы без общих полей.
  • Писать безопасные функции-обработчики для разных типов данных.
Список тем

1. Синтаксис оператора in

id: 40689_in_op_replace_syntax

В этом задании вам предстоит использовать оператор `in` для сужения типа объединения (union type). Функция `isBoat` принимает аргумент типа `Car | Boat`. Вам нужно дополнить код так, чтобы функция возвращала `true`, если переданный объект является лодкой (тип `Boat`), и `false` в противном случае. Для этого необходимо проверить наличие уникального свойства, которое есть только у лодки. Заполните пропуски корректными синтаксическими элементами, чтобы код компилировался и работал как описано.

Заполните пропуски
type Car = { wheels: number };
type Boat = { sails: boolean };

function isBoat(vehicle: Car | Boat): boolean {
    return 'sails' input1S vehicle;
}

// Пример использования:
const myCar: Car = { wheels: 4 };
const myBoat: Boat = { sails: true };

console.log(isBoat(myCar)); // false
console.log(isBoat(myBoat)); // true
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

2. Свойство и Тип

id: 40689_in_op_compare_props

В левой колонке перечислены названия типов данных TypeScript, а в правой — уникальные свойства, которые можно проверить с помощью оператора 'in' для сужения типа (type narrowing). Сопоставьте каждый тип с уникальным свойством, которое присутствует только в этом типе и может быть использовано для его идентификации. Обратите внимание, что в правой колонке свойства перемешаны.

Сопоставьте строки в правой(нижней) части с соответствующими строками в левой(верхней) по порядковому номеру
Admin
Guest
User
email
permissions
isAnonymous
Сообщения
Проверить
Показать подсказку

3. Ошибка в проверке

id: 40689_in_op_error_typo

В этом фрагменте кода TypeScript используется оператор `in` для проверки наличия свойства у объекта с целью сужения типа. Однако в условии проверки допущена опечатка в имени свойства, из-за чего код работает некорректно. Найдите и исправьте эту опечатку, чтобы условие правильно проверяло наличие свойства и сужало тип переменной.

Найдите ошибку и исправьте
type Admin = { name: string; role: string; };
type Guest = { name: string; email: string; };
 
let user: Admin | Guest = { name: "John", role: "admin" };
 
if ('nmae' in user) {
  console.log(user.name);
}
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

4. Логика проверки

id: 40689_in_op_sequencing_logic

Перед вами строки TypeScript-кода, демонстрирующие использование оператора `in` для сужения типов (type narrowing). Строки перемешаны. Восстановите правильный порядок строк, чтобы получилась корректная функция `processShape`, которая принимает объединение типов `Circle` и `Square`, проверяет наличие свойства `radius` с помощью оператора `in`, и в зависимости от результата выполняет соответствующее действие: для типа `Circle` вычисляет площадь, для типа `Square` — периметр. Убедитесь, что объявление функции, проверка свойства и ветвление if-else расположены в логически правильной последовательности.

Расставьте строки в правильном порядке
function processShape(shape: Circle | Square) {
    }
        console.log(`Area of circle: ${area}`);
        const area = Math.PI * shape.radius * shape.radius;
}
    if ('radius' in shape) {
    } else {
        console.log(`Perimeter of square: ${perimeter}`);
        const perimeter = 4 * shape.side;
Сообщения
Проверить
Показать подсказку

5. Результат сужения

id: 40689_in_op_predict_guard

Проанализируйте представленный код на TypeScript. В нём используется оператор `in` для проверки наличия свойства у объекта. Определите, какой конкретный тип будет иметь параметр `animal` внутри блока `if`, после того как проверка пройдёт. Выберите правильный вариант из предложенных.

Выберите правильный вариант ответа
interface Fish {
  swim: () => void;
}

interface Bird {
  fly: () => void;
}

function move(animal: Fish | Bird) {
  if ('swim' in animal) {
    // Какой тип имеет 'animal' внутри этого блока?
    animal.swim();
  } else {
    animal.fly();
  }
}

const myPet: Fish = { swim: () => console.log('Swimming') };
move(myPet);
Сообщения
Проверить
Показать подсказку

6. Выбор уникального ключа

id: 40689_in_op_select_fill_prop

В этом задании вам предстоит использовать оператор in для сужения типа (type narrowing) в TypeScript. Даны два интерфейса Circle и Square, представляющие геометрические фигуры. В функции getArea, которая принимает аргумент типа Circle | Square, необходимо правильно выбрать строковые значения для проверки наличия свойств с помощью оператора in, чтобы корректно вычислить площадь фигуры. Заполните пропуски в коде, выбирая подходящие варианты из выпадающего списка. Обратите внимание на то, какое свойство соответствует каждому интерфейсу.

Нужно правильно расставить в пропуски предложенные варианты
interface Circle {
  radius: number;
}

interface Square {
  sideLength: number;
}

function getArea(shape: Circle | Square): number {
  if (input1S in shape) {
    return Math.PI * shape.radius ** 2;
  } else {
    return shape.sideLength ** 2;
  }
}

const circle: Circle = { radius: 5 };
const square: Square = { sideLength: 4 };

console.log(getArea(circle)); // ~78.54
console.log(getArea(square)); // 16
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

7. Доступные свойства

id: 40689_in_op_click_target_narrowed

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

Кликните по всем фрагментам, которые подходят под условие задания.
interface Admin {
  role: string;
  permissions: string[];
}

interface Guest {
  isGuest: boolean;
  name: string;
}

function processUser(user: Admin | Guest) {
  if ('role' in user) {
    const a = {{user.role~|~t1}};
    const b = {{user.permissions~|~t2}};
    const c = {{user.isGuest~|~t3}};
    const d = {{user.name~|~t4}};
  }
}
Сообщения
Проверить
Показать подсказку

8. Функция-гард

id: 40689_in_op_build_guard

Из предложенных строк соберите корректную TypeScript-функцию-гард, которая принимает объект типа Circle или Square и возвращает true, если это Circle, используя оператор `in`. Функция должна использовать сужение типов (type narrowing) и возвращать предикат типа `shape is Circle`. Лишние строки в решение включать не нужно.

Перетяните в правильном порядке строки из одного блока в другой
type Circle = { radius: number };
type Square = { sideLength: number };
function isCircle(shape: Circle | Square): shape is Circle {
  return 'radius' in shape;
}
type Triangle = { sides: number };
function isSquare(shape: Circle | Square): shape is Square {
  return 'sideLength' in shape;
}
console.log(isCircle({ radius: 5 }));
Сообщения
Проверить
Показать решение на 3 сек.
Показать подсказку

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

id: 40689_compiler

В этом упражнении мы разберем, как оператор `in` помогает TypeScript автоматически определять тип объекта внутри блока условия. Попробуйте добавить новое уникальное свойство в один из интерфейсов и проверьте его наличие внутри функции — вы заметите, как IDE начинает подсказывать доступные методы именно для этого типа. Экспериментируйте: добавьте еще один тип (например, 'Guest'), расширьте объединение и попробуйте обработать его, используя изученный подход. Это отличный способ научиться безопасно работать с данными, когда вы не уверены на 100%, какой объект пришел на вход!

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