Динамически создавать наборы из объекта - PullRequest
0 голосов
/ 30 августа 2018

Скажите, у меня есть два следующих типа:

export type CollectionNames = 'twitter:tweets' | 'twitter:users' | 'twitter:metadata-cashtag'

export type CollectionType<T extends CollectionNames> = 
    T extends 'twitter:tweets' ? Tweet :
    T extends 'twitter:users' ? User :
    T extends 'twitter:metadata-cashtag' ? CashtagMetadataDb :
    never

Я чувствую, что это очень неуклюже, и я не очень хочу иметь струны дважды. Также возможно юридически неправильно их напечатать в последнем типе.

Есть ли способ создать их динамически из такого объекта, как этот:

typings = {
    'twitter:tweets': Tweet,
    'twitter:users': User,
    'twitters:metadata-cashtag': CashtagMetadataDb
}

Идея состоит в том, что несколько модулей будут иметь свой собственный тип CollectionType, который затем агрегируется в один CollectionType в корневом импортирующем модуле. Поэтому, если у меня есть два модуля Coin и Twitter, импортированные с использованием * as, это выглядит примерно так:

type CollectionName = Twitter.CollectionNames | Coin.CollectionNames

type CollectionType<T extends CollectionName> = 
    T extends Twitter.CollectionNames ? Twitter.CollectionType<T> :
    T extends Coin.CollectionNames ? Coin.CollectionType<T> :
    never

Затем они будут использоваться в функции, подобной той, где типы относятся к последнему типу (Collection здесь из MongoDB):

async function getCollection<T extends CollectionName> (name: T): Promise<Collection<CollectionType<T>>>

1 Ответ

0 голосов
/ 30 августа 2018

Я думаю, что в этом случае вам вообще не нужны условные типы; Вы можете сделать это с помощью keyof и типов поиска . Вы, вероятно, могли бы создать объект, подобный typings, и извлечь из него тип, но если вам не нужен этот объект для чего-то во время выполнения (и если бы объекты типа Tweet, User и т. Д. Лежали вокруг ) Я бы сказал, что вы должны просто сделать тип интерфейса следующим образом:

export interface Collections {
  'twitter:tweets': Tweet,
  'twitter:users': User,
  'twitter:metadata-cashtag': CashtagMetadataDb
}

Тогда ваши типы CollectionNames и CollectionType могут быть определены в терминах этого типа:

export type CollectionNames = keyof Collections;
export type CollectionType<K extends CollectionNames> = Collections[K];

Вы можете проверить, что вышеуказанные типы действуют так же, как ваши определения. В случае если у вас есть несколько модулей, которые экспортировали типы Collections, вы можете просто объединить их, используя расширение интерфейса, и извлечь из него CollectionNames и CollectionType:

export interface Collections extends Twitter.Collections, Coin.Collections {}
export type CollectionNames = keyof Collections;
export type CollectionType<K extends CollectionNames> = Collections[K];

Надеюсь, это поможет. Удачи!

...