Параметры и результат
Чему вы научитесь:
- находить функцию, которая возвращает обещанный тип не на каждом пути, и вызов с лишним или недостающим аргументом;
- объявлять необязательные параметры, параметры со значением по умолчанию и остаточные параметры;
- описывать тип функции и писать колбэки без лишних аннотаций;
- объявлять перегрузки и понимать, когда вместо них хватит объединения.

Подойдите к автомату с чаем. На табличке у монетоприёмника написано, что он берёт и что выдаёт: «Две монеты по 10 рублей — стакан чая». Табличку читают до того, как бросить монету: по ней видно, хватит ли денег и что вы получите взамен.
У функции JavaScript такой таблички нет. Функцию area(width, height) можно вызвать с одним аргументом: второй параметр получит undefined, 3 * undefined даст NaN, и программа пойдёт дальше с этим NaN. Ошибку заметят позже — там, где NaN окажется на экране.
В TypeScript табличку пишет автор функции. Типы параметров и результата вы уже умеете указывать: с них начиналась вторая тема. В этом уроке посмотрим, что tsc проверяет по такой табличке — каждый путь внутри функции и каждый вызов снаружи.
Сигнатура функции
function area(width: number, height: number): number {
return width * height;
}
console.log(area(3, 4)); // 12Первая строка и есть табличка автомата. Её называют сигнатурой функции: это имя, параметры с их типами и тип результата. Разберём её по частям:
area— имя функции;(width: number, height: number)— два параметра, оба числа: автомат берёт ровно две монеты;: numberпосле скобок — тип результата: функция обещает вернуть число.
По сигнатуре tsc проверяет функцию с двух сторон:
- Внутри функции — что каждый путь до конца тела возвращает обещанный тип.
- Снаружи — что каждый вызов передаёт столько аргументов, сколько у функции параметров, и нужных типов.
Результат на каждом пути
Функция может закончиться в разных местах: на одном return, на другом или на последней строке тела, если ни один return не встретился. В последнем случае JavaScript возвращает undefined. tsc проходит по всем путям и проверяет, что каждый возвращает тип из сигнатуры:
function grade(score: number): string { // ✗
if (score >= 50) {
return "зачёт";
}
}error TS2366: Function lacks ending return statement and return type does not include 'undefined'.Сообщение значит: «функции не хватает return в конце, а тип результата не включает undefined». При score меньше 50 условие не выполнится, функция дойдёт до конца тела и вернёт undefined. А сигнатура обещала строку. Поэтому ошибка стоит на типе результата в первой строке: нарушено именно это обещание.
Исправление — вернуть строку и на втором пути, например дописать return "незачёт"; после if.
Без аннотации : string ошибки на функции не было бы. TypeScript вывел бы тип результата "зачёт" | undefined, и undefined всплыл бы там, где результат используют как строку. Аннотация результата переносит проверку в саму функцию — туда, где ошибка и сделана.
Число аргументов
В JavaScript функцию можно вызвать с любым числом аргументов: недостающие получат undefined, лишние потеряются. TypeScript сверяет каждый вызов с сигнатурой:
function area(width: number, height: number): number {
return width * height;
}
console.log(area(3)); // ✗error TS2554: Expected 2 arguments, but got 1.Сообщение значит: «ожидалось 2 аргумента, а передан 1». Если бы JavaScript выполнил этот вызов, height получил бы undefined, и area вернула бы NaN. Лишний аргумент tsc тоже не пропустит: area(3, 4, 5) даст ту же ошибку с текстом Expected 2 arguments, but got 3.
Здесь аналогия с автоматом заканчивается. Настоящий автомат проверяет монеты в момент оплаты, а tsc сверяет вызовы с сигнатурой до запуска программы. При запуске JavaScript по-прежнему примет любое число аргументов: проверка была только в tsc.
Частая ошибка
Ветки if покрывают все случаи, которые вы держите в голове, и всё равно tsc сообщает об ошибке:
function sign(n: number): string { // ✗
if (n > 0) {
return "плюс";
} else if (n < 0) {
return "минус";
} else if (n === 0) {
return "ноль";
}
}error TS2366: Function lacks ending return statement and return type does not include 'undefined'.Кажется, что число бывает только положительным, отрицательным или нулём. Но tsc не проверяет, покрывают ли условия все числа: после последнего else if для него остаётся путь без return. И этот путь настоящий: у NaN ложны все три сравнения, и sign(NaN) вернул бы undefined. Последнюю проверку заменяют на else или пишут return после всех веток.
Главное
- Сигнатура функции — имя, параметры с типами и тип результата; по ней
tscпроверяет и тело функции, и каждый вызов. - Если хотя бы один путь доходит до конца тела без
return, функция с типом результатаstringдаёт ошибкуTS2366. - Вызов с недостающим или лишним аргументом — ошибка
TS2554, хотя JavaScript принял бы его молча. - Цепочку
else ifсreturnв каждой ветке заканчивают веткойelseилиreturnпосле всех веток.