Используйте, мы можем использовать Generi c Rest Parameters TypeScript, чтобы точно справиться с этим.
Это позволяет объявлять общий тип c кортежа, который фиксирует индивидуальный тип каждый аргумент при вызове функции.
Давайте разберем его.
Сначала мы зафиксируем тип каждого аргумента, переданного функции
const firstSettledValue = <P extends Promise<any>[]>(...promises: P) => {}
const v = firstSettledValue(
Promise.resolve('Hello World'),
Promise.resolve(15),
Promise.resolve(false)
)
Теперь, мы можем получить тип объединения для всех всех аргументов, то есть элементов P
, с помощью P[number]
.
type U = P[number] // string | number | boolean
Обратите внимание, что в приведенном выше P[0]
это тип string
, P[1]
- это тип number
и т. Д.
Однако мы не можем использовать P[Number]
непосредственно в приведенном выше коде, потому что наши элементы являются обещаниями, и нам нужно извлечь их значение типов.
Для этого мы можем ввести небольшой вспомогательный тип
type ValueType<T> = T extends Promise<infer U>
? U
: T;
Учитывая Promise<T>
, приведенный выше помощник производит T
.
Наконец, мы составьте эти техники вместе
const firstSettledValue = <P extends Promise<any>[]>(...promises: P): Promise<ValueType<P[number]>> => {
const randomIndex = Math.floor(Math.random() * 100) % promises.length;
return promises[randomIndex];
};
const v = firstSettledValue(
Promise.resolve('Hello World'),
Promise.resolve(15),
Promise.resolve(false)
);
type ValueType<T> = T extends Promise<infer U>
? U
: T;
Playground Link
И мы сделали. v
имеет тип Promise<string | number | boolean>
на основе обещаний, указанных в вызове.