Сегодня разберем rest- и spread-операторы.
Rest-оператор позволяет создавать функции с переменным числом параметров, при этом сворачивать их в массив:
function max(...numbers: number[]): number {
return Math.max(...numbers);
}
Этот массив является обычным параметром функции, поэтому ему задается тип в соответствии с тем, какие значения ожидаются внутри этого массива. Пример с двумя параметрами:
function do(operation: string, ...numbers: number[]) {
// выполняем операцию operation для всех numbers
}
В этом смысле rest-оператор в TypeScript ничем не отличается от rest-оператора в JavaScript. А вот со spread-оператором есть одна особенность.
Spread-оператор в функциях — это как rest-оператор наоборот. Он позволяет раскладывать массив на отдельные параметры:
const numbers = [1, 2, 3];
Math.max(...numbers);
Если функция принимает на вход любое количество аргументов, как в примере выше, то такой код работает без проблем. Но если функция принимает на вход определенное число аргументов, то TypeScript выдаст ошибку компиляции:
function sum(a: number, b: number): number {
return a + b;
}
// Выведенный тип number[] — "ноль или больше чисел",
// а не "массив из двух чисел"
const args = [1, 2];
sum(...args);
// A spread argument must either have a tuple type
// or be passed to a rest parameter.
В примере выше TypeScript не может понять, что массив args
состоит из двух чисел. Массивы в JavaScript изменяемы, поэтому TypeScript не может полагаться на количество элементов в конкретный момент времени. Есть разные способы обойти это ограничение. Но в этой ситуации проще использовать Type Assertion — указание компилятору, что мы точно знаем о коде:
const args = [1, 2] as const;
Подробнее о Type Assertion поговорим в модуле о типах. С его помощью мы явно указываем, что этот массив состоит из двух конкретных значений, которые не поменяются.
Определите функцию max()
, которая отличается от примера из урока только тем, что у нее первый параметр обязательный.
Например:
max(1,2,3);
max(234);
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Привет! Я Тота и моя задача помочь в обучении. Чтобы активировать меня, нужно зарегистрироваться или залогиниться, если у вас уже есть аккаунт
Ваше упражнение проверяется по этим тестам
1import { expect, test } from 'vitest'
2import max from './index';
3
4test('function', () => {
5 expect(max(1, 3, 8)).toBe(8);
6 expect(max(10)).toBe(10);
7 expect(max(4, 1)).toBe(4);
8});
9
Решение учителя откроется через: