从对象动态创建类型
Create typings dynamically from object
假设我有以下两种类型:
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>>>
我认为在这种情况下你根本不需要条件类型;你可以用 keyof
and lookup types 代替。您可能 可以 创建一个像 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];
希望对您有所帮助。祝你好运!
假设我有以下两种类型:
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>>>
我认为在这种情况下你根本不需要条件类型;你可以用 keyof
and lookup types 代替。您可能 可以 创建一个像 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];
希望对您有所帮助。祝你好运!