网站搜索

node.js - 在库中提供可扩展的 Typescript 接口


我正在使用 TypeScript 构建一个应该支持第三方插件的库。库的构造函数应该接受核心库和所有插件的选项,因为模块将在构造函数中加载它们。

是否可以提供一个基础的 Options 接口,每个插件都可以扩展它以添加自己的属性和类型,从而在整个顶层应用程序(使用该库和插件)中,Options 接口既反映核心选项,也反映插件的选项?

所以像这样的依赖结构:

- user-app
|- my-library
|- my-library-plugin-a
|- my-library-plugin-b

其中 my-library 定义了以下内容:

export interface Options {
  coreOption : string;
}

并且 my-library-plugin-a 如下扩展它:

export interface PluginAOptions extends Options {
  pluginA : boolean;
}

并且 my-library-plugin-b 如下扩展它:

export interface PluginBOptions extends Options {
  pluginB : Record<string, string>;
}

对于 user-app 的开发者,该应用在其依赖项中包含所有三个模块,从 my-library 导出的 Options 接口应如下所示:

interface Options {
  coreOption : string;
  pluginA : boolean;
  pluginB : Record<string, string>;
}

所以这就是他们的自动完成应该显示的内容,以及 TypeScript 编译器应该检查的内容。

使用 Typescript 这样的东西有可能吗?

答案#1

你不能指望从 my-library 获得所有扩展选项。

这不是关于 TypeScript 的问题,而是关于依赖关系的工作原理。my-library 对插件一无所知,而且它本该如此。如果它以某种方式可以导出插件添加的选项,那么它将依赖于那些插件,从而使插件架构变得毫无意义。

在 user-app 中,你只需使用 plugin-a 和 plugin-b 的选项并将它们组合起来。

const theOption: PluginAOptions & PluginBOptions = { ... }

user-app 是知道并决定使用 plugin-a 和 plugin-b 的人。这就是为什么它应该并且可以使用这些插件中的类型。

答案#2

这可以使用 TypeScript 的声明合并功能实现:

我的库:

export interface Options {
  coreOption : string;
}

my-library-plugin-a:

import {Options} from 'my-library';

export module 'my-library' {
    export interface Options {
      pluginA: boolean;
    }
}

my-library-plugin-b:

import {Options} from 'my-library';

export module 'my-library' {
    export interface Options {
      pluginB: Record<string, string>;
    }
}