【发布时间】:2019-05-29 15:30:45
【问题描述】:
我正在尝试定义一个通用 Typescript 接口,该接口将对一系列模块的导出强制执行一种模式。每个模块都将导出 Apollo GraphQL 服务器的各个部分,这些部分可以拼接在一起以提高可扩展性。
例如,假设我有一个名为 News 的文件夹,其结构如下:
News
|_ index.ts
|_ typeDefs.ts
|_ resolvers.ts
|_ dataSources
|_ index.ts
|_ SourceA.ts
|_ SourceB.ts
在 index.ts 的新闻中,我定义了以下内容:
import { IResolvers } from "apollo-server";
import { DocumentNode } from "graphql";
import * as DataSources from "./datasources";
import resolvers from "./resolvers";
import schema from "./typeDefs";
export interface IContext {
dataSources: {
[R in keyof typeof DataSources]: InstanceType<typeof DataSources[R]>
};
}
interface IModule {
resolvers: IResolvers;
schema: DocumentNode;
dataSources: typeof DataSources;
}
export const News: IModule = {
resolvers,
schema,
dataSources: DataSources
};
这完全符合我的要求,它允许我确保导出的 News 对象包含正确的数据源,我可以在需要时实例化这些数据源,并确保当这些数据源返回请求上下文时,它们将是我定义的数据源的实例。
接下来我想做的是能够将IModule 和IContext 应用到另一个我们称为Foo 的模块。 Foo 与 News 具有相同的结构,但会导出自己的 DataSource。
如何修改这些类型以支持多个模块,其中数据源将嵌套在每个单独的模块下?
编辑:
我可以通过传入泛型类型来更新IModule:
interface IModule<TDataSources> {
resolvers: IResolvers;
schema: DocumentNode;
dataSources: TDataSources;
}
const News: IModule<typeof DataSources> = {
resolvers,
schema,
dataSources: DataSources
};
这似乎工作正常。
一般来说,我想要一个看起来像这样的对象:
{
modules: {
Foo: {
resolvers,
schema,
dataSources: {
DataSourceA,
DataSourceB
},
},
Bar: {
resolvers,
schema,
dataSources: {
DataSourceC,
DataSourceD
},
},
}
}
然后把它变成这样:
{
DataSourceA,
DataSourceB,
DataSourceC,
DataSourceD
}
同时维护每个 DataSource 上的类型。映射本身不是问题,它从较大的模块对象中提取每个 DataSource 的类型以创建所有 DataSource 的联合类型。
【问题讨论】:
-
能否请您澄清一下结合多个数据源的最终接口应该是什么样子?可能是完全无效的 TypeScript,但可能有助于了解您要实现的目标。
-
@Grassator - 我在上面提供了更多详细信息。