TypeScript поддерживает точную типизацию функций с использованием rest-параметров и деструктуризации. Это особенно важно для функций, принимающих переменное число аргументов или сложные объекты.
Деструктуризация в параметрах функции позволяет явно указать структуру ожидаемых свойств:
function printUser({ name, age }: { name: string; age: number }) { console.log(`${name} (${age})`); }
Rest-параметры позволяют задать переменное число аргументов и их тип:
function sum(...numbers: number[]): number { return numbers.reduce((acc, cur) => acc + cur, 0); }
Комбинированное использование встречается в функциях, которые принимают основной объект и дополнительный массив параметров:
function logEvent(event: { type: string }, ...meta: any[]) { console.log(event.type, meta.join(',')); }
Корректная типизация позволяет выявить ошибки до выполнения кода, но неправильная типизация приведет к потере безопасности типов и ошибкам в рантайме.
Как задать тип для функции с деструктурированными параметрами по умолчанию и сделать их необязательными?
Многие указывают тип объекта, но забывают сделать каждое поле опциональным или задать значения по умолчанию одновременно с типом:
function foo({x = 1, y = 2}: {x?: number; y?: number} = {}) { console.log(x, y); }
Здесь заданы значения по умолчанию и все параметры делают необязательными с помощью ?. Без этого вызов без параметров вызовет ошибку, хотя ожидается дефолт.
История
undefined нет свойства name.История
any[], что допустило передачу не только чисел. На production внезапно сложили числа и строки, получив некорректные результаты в отчетах.История
Использовали деструктуризацию с глубоко вложенным объектом, но не указали вложенные типы. Из-за этого TS "потерялся" и не подсказал отсутствие обязательного поля в объектах, что привело к ошибке TypeError: Cannot read property 'id' of undefined на стороне клиента.