Вы можете сделать это, используя условные типы и сопоставленный тип:
class X{}
class Y{}
class Z{}
export const v = {
a() : Promise<X>{
return null as any;
},
b() : Promise<Y>{
return null as any;
},
c() : Promise<Z>{
return null as any;
},
}
type ExtractAllPromisses<T> =
{
// Take all keys of T ([P in keyof T])
// and if the property P of T is a promise returning function (T[P] extends ()=> Promise<infer U>)
// then the new type of P will be the return type of the promise (saved in U)
// Otherwise the new type of P is never
[P in keyof T]: T[P] extends ()=> Promise<infer U> ? U : never
};
export type V = ExtractAllPromisses<typeof v> // same as type V = { a: X; b: Y; c: Z; }
Существуют варианты, которые вы можете сделать в условном типе в зависимости от ваших потребностей. Приведенный выше пример работает специально для типа, который имеет только функции, которые не принимают аргументов и возвращают Promise
Если вы хотите сопоставить функцию с любым количеством аргументов, которые вы можете использовать:
type ExtractAllPromisses<T> = { [P in keyof T]: T[P] extends (...args: any[])=> Promise<infer U> ? U : never };
Если ваш тип также имеет свойства, которые не являются обещающими возвращающими функциями, и вы хотите сохранить эти свойства (т. Е. v
также имеет поле foo:number
), вы можете использовать:
type ExtractAllPromisses<T> = { [P in keyof T]: T[P] extends (...args: any[])=> Promise<infer U> ? U : T[P] };
Если вы хотите исключить свойства, которые не являются функцией повторной настройки обещания. Вы можете отфильтровать ключи:
type PromiseFunctionFields<T> = { [P in keyof T] : T[P] extends (...args: any[])=> Promise<any> ? P : never}[keyof T];
type ExtractAllPromisses<T> = { [P in PromiseFunctionFields<T>]: T[P] extends (...args: any[])=> Promise<infer U> ? U : T[P] };