首页 > 解决方案 > TypeScript:如何合并使用相同全局属性的接口声明?

问题描述

我有一个使用多个cordova插件的打字稿项目。plugins每个插件都在一个全局对象上初始化,如下所示:

// Plugin A init
window.plugins.pluginA = {...};

// Plugin B init
window.plugins.pluginB = {...};

但是,我无法弄清楚如何处理类型,以便每个插件都可以在plugins不知道其他插件的情况下扩展对象。第二个插件的类型会抛出错误,因为该plugins对象已被定义。我如何构建它来扩展它?

// Plugin A's type declarations
interface IPluginA {
    methodA: (foo: number) => void
}
interface Window {
    plugins: {
        pluginA: IPluginA;
    };
}

// Plugin B's type declarations
interface IPluginB {
    methodB: (bar: string) => void
}
interface Window {
    // ERROR: Subsequent property declarations must have the same type.
    //     Property 'plugins' must be of type '{pluginA: IPluginA};'
    plugins: {
        pluginB: IPluginB;
    };
}

标签: typescripttypesinterface

解决方案


据我了解,您想要做的是从其他两种具有一些共同结构的类型中加入类型 -plugins属性。为了实现这一点,我们可以使用联合类型 - type Union = A | B

在您的示例中,它将是:

// specific plugins types
type IPluginA = {
    methodA: (foo: number) => void
}
type IPluginB = {
    methodB: (bar: string) => void
}

type WindowA = {
  plugins: {
      pluginA?: IPluginA
    }
}

type WindowB = {
  plugins: {
      pluginB?: IPluginB
    }
}

type MyWindow = WindowA | WindowB; // here union of both

const win: MyWindow = {
  plugins: {
    // pluginA and pluginB as fields
  }
}

如果会有新的插件,我们可以将它们进一步附加到MyWindow,这要归功于我们的最终类型将拥有所有可能的插件。再看看我把可选字段放在那里,因为可能没有所有插件,但只有一部分。


推荐阅读