【问题标题】:How to merge namespace has no exported interface in TypeScript如何合并命名空间在 TypeScript 中没有导出的接口
【发布时间】:2018-04-09 02:43:36
【问题描述】:

我在 TypeScript 中使用队列库 Bull。它的定义是:

node_modules/@types/bull/index.d.ts

declare const Bull: {
  (queueName: string, opts?: Bull.QueueOptions): Bull.Queue;
  // something like above
};

declare namespace Bull: {
  interface Queue {}
  interface Job {}

  // some other non-exported interfaces
}

export = Bull

我想在我的库中合并命名空间Bull 并在另一个应用程序中使用它。

node_modules/myLib/index.d.ts

import { Queue } from 'bull'

declare namespace Bull: {
  export interface Queues {}
}

export interface myInterface {
  foo: Queue | Bull.Queues
}

export = Bull

myApp/foo.ts

import { Job, Queues } from 'myLib' // Error, 'myLib' has no exported member 'Job'

根据文档,namespace 是一个 GLOBAL 变量,同名的命名空间会合并它们的 EXPORTED 接口。那么,如何将命名空间 Bull@types/bull 合并?谢谢!

【问题讨论】:

    标签: typescript bull.js


    【解决方案1】:

    嗯,事实上@types\bull 并没有真正声明一个命名空间。

    嗯,是的,但只是将相关类型的列表分组并一起导出为默认导出,所以,它真正导出的是命名空间的内容,而不是命名空间本身.这就是为什么你可以导入Queue,并使用Queue而不是Bull.Queue,如果Queue真的属于一个命名空间,你应该这样做。

    此外,我不知道您使用的是什么版本的 TypeScript,但您不应该在同一个文件中使用 export (...)export = (...)。另外,当你在一个文件中添加export时,它会变成一个模块的声明文件,所以,最后你有一个默认导出命名空间的模块,然后你可以从@987654330导入Queues @,但不是 Job,因为 Job 不会出现在文件中的任何位置,因此不会导出。

    为了能够合并不同文件中的命名空间,您不能使用导入或导出,只能使用声明,因为两个模块永远不能为同一个命名空间提供名称。通过使用export,您将文件转换为模块,一旦这样做,其中的命名空间不再属于全局范围,因此即使它们具有相同的名称,它们也确实属于它们的范围自己的模块,不要合并。

    要做你想做的事,你必须:

    公牛:

    declare const Bull: {
        (queueName: string, opts?: any): Bull.Queue;
        // something like above
      };
    
    declare namespace Bull {
        interface Queue {}
        interface Job {}
    
        // some other non-exported interfaces
    }
    

    我的库:

    declare namespace Bull {
      export interface Queues {}
    }
    
    declare interface myInterface {
      foo: Bull.Queue | Bull.Queues
    }
    

    现在您真正拥有了一个包含两个声明内容的命名空间:

    test.ts:

    const a: Bull.Queues = {};
    const g: Bull.Queue = {};
    const b: Bull.Job = {};
    

    这样它会起作用,但不幸的是,这不是你所拥有的。您应该将myLib 定义为:

    import * as Bull from './bull';
    
    export interface Queues {};
    
    
    export interface myInterface {
      foo: Bull.Queue | Queues;
    }
    

    然后你可以使用:

    import * as Bull from './bull';
    import { Queues, myInterface } from './myLib';
    
    const a: Queues = {};
    const g: Bull.Queue = {};
    const b: Bull.Job = {};
    
    const instance: myInterface = null;
    

    或者,如果你愿意,

    import * as Bull from './bull';
    import * as ExtendedBull from './myLib';
    
    const a: ExtendedBull.Queues = {};
    const g: Bull.Queue = {};
    const b: Bull.Job = {};
    
    const instance: ExtendedBull.myInterface;
    

    但是,无论如何,您都需要从bullmyLib 导入。

    【讨论】:

    • 谢谢。我正在使用myLib 中的export { Queue, Job, ...} from 'bull' tmp 解决方案。也不是什么好办法。似乎我必须分别导入bullmyLib。我会接受这个答案,因为它解释了为什么合并的事情不起作用。
    猜你喜欢
    • 2018-12-13
    • 1970-01-01
    • 2019-06-29
    • 2020-10-22
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    相关资源
    最近更新 更多