> Как типизировать функцию, работающую с массивом промисов с разными типами в TypeScript (TypeScript)
Уровень: senior · Роль: frontend · Категория: Технические вопросы
Компании: IT-One
Стек: TypeScript
> Пример ответа
Короткий ответ
Для типизации функции с массивом промисов разных типов используйте дженерики с variadic tuple types: function all<T extends readonly unknown[]>(promises: {[K in keyof T]: Promise<T[K]>}): Promise<T>. Это позволяет сохранить точные типы каждого элемента. Альтернатива - Promise.all с mapped types или ручное указание перегрузок для ограниченного числа элементов.
Подробное объяснение
Основная задача - сохранить связь между типом каждого промиса в массиве и соответствующим значением в результате. TypeScript 4.0+ предоставляет variadic tuple types, которые идеально подходят для этой цели.
Механизм работы:
- Дженерик
T extends readonly unknown[]захватывает кортеж типов результата - Mapped type
{[K in keyof T]: Promise<T[K]>}преобразует каждый элемент кортежа в промис того же типа - Возвращаемый тип -
Promise<T>с сохранением структуры кортежа
Для функции, которая не просто вызывает Promise.all, а выполняет дополнительную логику (например, обработку ошибок, фильтрацию, трансформацию), типизация строится аналогично, с учётом конкретных преобразований.
На практике
Используйте встроенный Promise.all - он уже правильно типизирован для кортежей. Если пишете свою реализацию, применяйте variadic tuple types. Для динамических массивов (не кортежей) используйте Promise<T[]>, где T - объединение возможных типов.
Примеры сценариев:
- Параллельная загрузка данных разных типов
- Комбинирование результатов нескольких API-запросов
- Обработка массива промисов с разными типами ошибок
Пример кода
TYPESCRIPT// Базовая типизация с variadic tuple typesfunction allPromises<T extends readonly unknown[]>(promises: { [K in keyof T]: Promise<T[K]> }): Promise<T> {return Promise.all(promises) as Promise<T>;}// Использованиеconst result = await allPromises([Promise.resolve(42),Promise.resolve("hello"),Promise.resolve(true)]);// result: [number, string, boolean]// Функция с трансформациейasync function transformAll<T extends readonly unknown[], R>(promises: { [K in keyof T]: Promise<T[K]> },transform: (values: T) => R): Promise<R> {const values = await Promise.all(promises) as T;return transform(values);}// Для динамических массивовasync function processPromises<T>(promises: Promise<T>[]): Promise<T[]> {return Promise.all(promises);}
Как отвечать на собеседовании
Начните с ключевой идеи - variadic tuple types. Объясните, как mapped types сохраняют соответствие типов. Упомяните, что встроенный Promise.all уже корректно типизирован. Приведите пример с разными типами. Если спросят про ограничения - скажите, что для динамических массивов (неизвестное количество элементов) придётся использовать объединение типов.
Что проверяет интервьюер
- Понимание продвинутых дженериков TypeScript
- Знание variadic tuple types и mapped types
- Умение типизировать асинхронные операции
- Понимание разницы между кортежами и массивами в контексте типов
- Способность объяснить, как TypeScript выводит типы для промисов
Типичные ошибки
- Использование
Promise<any[]>- теряет всю типовую информацию - Попытка типизировать через перегрузки для каждого количества элементов - негибко и громоздко
- Забывают про
readonlyв дженерике для кортежей - Путают
Promise<T[]>с кортежем промисов - Не учитывают, что
Promise.allсам корректно выводит типы для кортежей
> Похожие задачи по frontend
Что такое TypeScript
Можно ли создать константу с несуществующим типом в TypeScript?
Как реализовать функцию getProperty с типизацией в TypeScript, которая возвращает значение по ключу объекта?
Что такое utility types в TypeScript, например Partial и DeepPartial
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью