Бесплатный курс по TypeScript. Зарегистрируйтесь для отслеживания прогресса →

TypeScript: Функции как параметры

В TypeScript используется несколько способов типизировать функции, которые передаются как параметры. В этом уроке мы научимся работать с ними.

Как типизировать функции, которые передаются как параметры

Самый простой способ типизировать функции как параметры — использовать тип Function. Он описывает функцию JavaScript со всеми ее особенностями, включая свойства bind, call и apply.

Опишем входной параметр callback функции process:

function process(callback: Function) {
  const value = callback();
  // ...
}

Function отключает проверку типов для вызываемой функции. В итоге количество и тип входных аргументов не проверяются, а результатом работы такой функции будет any. Это может привести к логическим ошибкам и неожиданному поведению:

process(Math.round); // ?

Данный пример сработает, хотя поведение вряд ли будет ожидаемым, так как Math.round вызовется без аргументов и вернет NaN. Поэтому мы рекомендуем избегать использования Function.

Другой способ описывать функции — использовать стрелочную функцию с указанием входных и выходных типов:

function process(callback: () => string) {
  // value имеет тип string
  const value = callback();
  // ...
}

process(Math.round);
// Argument of type '(x: number) => number' is not
// assignable to parameter of type '() => string'.

Определение стрелочной функции похоже на настоящую, но тут важно не перепутать. Здесь мы видим именно описание типа, а не определение функции.

Рассмотрим еще несколько примеров для закрепления:

function process(callback: () => number)
function process(callback: () => string[])
function process(callback: () => { firstName: string; })

Параметры синтаксически указываются так же, как и для стрелочных функций:

function process(callback: (n: number) => string) {
  const value = callback(10);
  // ...
}

Здесь мы определили тип callback функцией с параметром n с типом number и возвращаемое значение string.

Если определение функции встречается часто, то для него можно создать псевдоним:

type myFunction = (n: number) => string;

function process(callback: myFunction) {
  const value = callback(10);
  // ...
}

Такая запись упрощает чтение кода и позволяет избежать дублирования.

Задание

Реализуйте функцию filter(), которая принимает на вход массив чисел и предикат. Последний будет использоваться для проверки каждого числа на соответствие требованиям:

const numbers = [1, -5, 2, 3, 4, 133];
filter(numbers, (n) => n > 3); // [4, 133]
filter(numbers, (n) => n % 2 == 0); // [2, 4]

Параметры функции:

  1. Массив чисел
  2. Анонимная функция, которая принимает на вход число и возвращает логическое значение
Упражнение не проходит проверку — что делать? 😶

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет 🤨

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя 🤔

Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно 🙄

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.

Полезное


Нашли ошибку? Есть что добавить? Пулреквесты приветствуются https://github.com/hexlet-basics
Если вы столкнулись с трудностями и не знаете, что делать, задайте вопрос в нашем большом и дружном сообществе