Как типизировать функции в TypeScript?
Вопрос
Как типизировать параметры и возвращаемое значение функции, задавать опциональные/значения по умолчанию и что такое перегрузки функций?
Короткий ответ
Типы параметров указываются после имени через двоеточие, тип возврата — после списка параметров. Опциональные параметры помечаются ?, параметры со значением по умолчанию сами выводят тип. Перегрузки (function overloads) позволяют описать несколько сигнатур для одной функции с разным поведением в зависимости от типов аргументов.
Подробный ответ
Базовая типизация функции:
function sum(a: number, b: number): number {
return a + b
}
Тип возвращаемого значения обычно можно не указывать явно — TypeScript выведет его сам, но в публичных API (экспортируемых функциях) хорошей практикой считается указывать его явно, чтобы случайное изменение тела функции не поменяло контракт незаметно.
Опциональные параметры (?) могут быть не переданы — тогда их значение undefined. Они обязаны идти после обязательных:
function createUser(name: string, age?: number) {
// age: number | undefined
}
Параметры по умолчанию делают параметр опциональным при вызове, а TypeScript выводит его тип из значения по умолчанию, если тип не указан явно:
function createUser(name: string, role = 'user') {
// role: string, при вызове необязателен
}
Перегрузки функций нужны, когда поведение и тип возврата функции зависят от формы входных аргументов так, что union-типа недостаточно для точного описания связи вход → выход. Пишется несколько сигнатур подряд, а следом — одна реализация, которая должна быть совместима со всеми сигнатурами (сама реализация не видна вызывающему коду):
function makeDate(timestamp: number): Date
function makeDate(day: number, month: number, year: number): Date
function makeDate(a: number, b?: number, c?: number): Date {
if (b !== undefined && c !== undefined) return new Date(c, b - 1, a)
return new Date(a)
}
makeDate(2026) // OK — первая сигнатура
makeDate(7, 9, 2026) // OK — вторая сигнатура
makeDate(7, 9) // Ошибка — нет сигнатуры с двумя аргументами
Без перегрузок пришлось бы писать (a: number, b?: number, c?: number) => Date, и тогда вызов makeDate(7, 9) не был бы отклонён компилятором.
Пример
interface FetchOptions {
method?: 'GET' | 'POST'
retries?: number
}
// явный тип возврата в публичной функции
async function fetchData<T>(url: string, options: FetchOptions = {}): Promise<T> {
const { method = 'GET', retries = 3 } = options
const res = await fetch(url, { method })
if (!res.ok) throw new Error(`Failed: ${res.status}`)
return res.json() as Promise<T>
}
// перегрузки для парсера конфигурации
function parseConfig(input: string): Record<string, string>
function parseConfig(input: string[]): Record<string, string>[]
function parseConfig(input: string | string[]): Record<string, string> | Record<string, string>[] {
const parseOne = (s: string) => JSON.parse(s) as Record<string, string>
return Array.isArray(input) ? input.map(parseOne) : parseOne(input)
}
Дополнительные вопросы
- Чем сигнатура функции с union-параметром отличается от перегрузок и когда выбрать одно вместо другого?
- Как типизировать функцию, принимающую произвольное число аргументов (
rest parameters)? - Что такое
thisпараметр в типизации функций и зачем он нужен?