从 Object => Object 映射 TypeScript 类型

Mapping TypeScript types from Object => Object

假设我有一个这样的对象:

export const v = {
   a() : Promise<X>{

   },
   b() : Promise<Y>{

   },
   c() : Promise<Z>{

   }
}

我的问题是 - 有没有办法获取 v 的类型,但映射类型,使其看起来像这样:

export type V = {
  a: X, 
  b: Y,
  c: Z
}

基本上我将对象中的每个键映射到各自承诺的解析值。

基本上,我试图从静态声明的内容派生修改后的类型。

您可以使用条件类型和映射类型执行此操作:

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

根据您的需要,您可以在条件类型中做一些变体,上面的示例专门适用于只有不带参数的函数和 return a Promise

如果你想用任意数量的参数匹配一个函数,你可以使用:

type ExtractAllPromisses<T> = { [P in keyof T]: T[P] extends (...args: any[])=> Promise<infer U> ? U : never };

如果您的类型还具有不承诺 returning 函数的属性,并且您想保留这些属性(即 v 也有一个字段 foo:number),您可以使用:

type ExtractAllPromisses<T> = { [P in keyof T]: T[P] extends (...args: any[])=> Promise<infer U> ? U : T[P] };

如果你想排除不是promise重调函数的属性。您可以过滤键:

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