Отображение типов TypeScript из Object => Object - PullRequest
0 голосов
/ 09 мая 2018

Скажем, у меня есть такой объект:

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

   },
   b() : Promise<Y>{

   },
   c() : Promise<Z>{

   }
}

мой вопрос - есть ли способ получить тип v, но сопоставить тип так, чтобы он выглядел примерно так:

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

В основном я сопоставляю каждый ключ в объекте с разрешенным значением соответствующего обещания.

По сути, я пытаюсь получить модифицированный тип из того, что объявлено статически.

1 Ответ

0 голосов
/ 09 мая 2018

Вы можете сделать это, используя условные типы и сопоставленный тип:

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