Функции - основные строительные блоки любого приложения, написанного как на JavaScript, так и на TypeScript. Но TypeSript привносит ряд новшеств и упрощает работу с ними.
Создаются функции с помощью ключевого слова function
. Они могут быть анонимными или именованными:
// Анонимная функция
let sumFunc = function (a, b) {
return a + b;
};
// Именованная функция
function sum(a, b) {
return a + b;
}
Типизация функций
Типы параметров функции
Каждый параметр функции может иметь свой тип, который указывается через знак двоеточия:
function sum(a: number, b: number) {
return a + b;
}
Тип возвращаемого значения
Также в TypeScript можно задать тип значения, которое должна вернуть функция:
function sum(a: number, b: number): number {
return a + b;
}
Полный тип функции
Полный тип функции собственно состоит из типов параметров функции и типа значения, возвращаемого этой функцией:
let sum: (a: number, b: number) => number;
sum = function(x: number, y: number): number {return x + y};
При описании полного типа функции тип возвращаемого значения указывается через жирную стрелку =>
. Названия параметров в строке описания типа функции не имеют значения. Их проверка производится по порядку, и они могут не совпадать с названиями параметров в реализации самой функции. Если функция ничего не возвращает, то указывается тип void
.
Компилятор TypeScript может выводить тип из контекста функции и описание типов можно не дублировать:
let sum: (a: number, b: number) => number = function(x, y) {return x + y};
Необязательные параметры функции
TypeScript, в отличие от JavaScript, требует, чтобы при вызове функции число параметров, которые в нее передаются, строго соответствовало числу параметров, описанных в ее типе. В то время как в JS при вызове функции некоторые параметры можно было не указывать, в TS подобное вызовет ошибку. Указать, что параметр является опциональным, можно при описании параметров, добавив в конце названия параметра ?
:
function sum(a: number, b: number, c?: number): number {
if (c)
return a + b + c;
else
return a + b;
}
let result;
result = sum(1); // Ошибка: не хватает параметров
result = sum(1, 2); // OK
result = sum(1, 2, 3); // OK
result = sum(1, 2, 3, 4); // Ошибка: избыток параметров
Все опциональные параметры должны следовать за обязательными. Если при вызове функции значение необязательного параметра не задано, то ему будет присвоено значение undefined
.
Параметры функции по умолчанию
Для некоторых параметров функции можно задать значение по умолчанию. Оно будет присвоено данному параметру, когда при вызове функции данный параметр будет опущен или undefined
.
function sum(a: number, b: number, c = 0): number {
return a + b + c;
}
let result;
result = sum(1, 2); // 3
result = sum(1, 2, 3); // 6
Если параметр со значением по умолчанию находится после обязательных параметров, то он является опциональным и может быть опущен. Но его нахождение в конце не является обязательным.
Остаточные параметры функции
Бывает, что функция должна работать с переменным числом аргументов и заранее это число не известно. А прописывать опциональные параметры на все случаи жизни не разумно. Для таких случаев можно использовать конструкцию остаточных (...rest) параметров:
function sum(a: number, ...terms: number[]): number {
let s = a;
terms.forEach(function(term:number){
s += term;
})
return s;
}
let result;
result = sum(1, 2); // 3
result = sum(1, 2, 3, 4, 5); // 15
Пишем многоточие перед названием последнего параметра terms
. При вызове этой функции первое значение будет присвоено параметру a
, а все последующие будут записаны в массив с именем terms
.
Перегрузка функций
Иногда функция должна возвращать значения, тип которых зависит от входящих параметров. В этом случае для описания типа такой функции нужно использовать перегрузку - перечисление всех возможных типов данной функции.
Предположим у нас есть функция, которая должна возвращать нам пользователя. Причем по имени пользователя она должна возвращать числовую айдишку, а по id
- его имя. Перегрузка такой функции будет выглядеть следующим образом:
function getUser(id: number): string;
function getUser(name: string): number;
function getUser(value: number|string): string|number {
if (typeof value === 'string') {
let id: number = getUserByName(value);
return id;
} else if (typeof value === 'number'){
let userName: string = getUserById(value);
return userName;
}
}
В итоге мы имеем довольно гибкую функцию и рабочую проверку типов. Вызов этой функции с типом параметра, отличным от числового или строкового, вызовет ошибку.