ПрограммированиеFrontend-разработчик

Как работает типизация функций с REST и деструктуризацией параметров в TypeScript? Какие ошибки возникают при неправильной типизации таких функций?

Проходите собеседования с ИИ помощником Hintsage

Ответ

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); }

Здесь заданы значения по умолчанию и все параметры делают необязательными с помощью ?. Без этого вызов без параметров вызовет ошибку, хотя ожидается дефолт.

Примеры реальных ошибок из-за незнания тонкостей темы


История

В проекте при миграции функции с параметрами с JavaScript на TypeScript, тип указали только объекту, а не отдельным полям. В итоге вызов функции без параметров привёл к падению приложения с ошибкой деструктуризации: у undefined нет свойства name.

История

При работе с rest-параметрами забыли явно указать тип массива. В функции тип был any[], что допустило передачу не только чисел. На production внезапно сложили числа и строки, получив некорректные результаты в отчетах.

История

Использовали деструктуризацию с глубоко вложенным объектом, но не указали вложенные типы. Из-за этого TS "потерялся" и не подсказал отсутствие обязательного поля в объектах, что привело к ошибке TypeError: Cannot read property 'id' of undefined на стороне клиента.