如何合并命名空间在 TypeScript 中没有导出接口
How to merge namespace has no exported interface in TypeScript
我在 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'
根据文档,命名空间是一个全局变量,同名的命名空间将合并它们的导出接口。那么,如何从 @types/bull
合并命名空间 Bull
?谢谢!
嗯,事实是 @types\bull
并没有真正声明命名空间。
嗯,是的,只是把相关类型的列表归为一组,作为默认导出一起导出,所以,它真正导出的是namespace的contents ,而不是命名空间本身。这就是为什么您可以导入 Queue
,并使用 Queue
而不是 Bull.Queue
,如果 Queue
确实属于某个命名空间,您应该这样做。
此外,我不知道你使用的是什么版本的 TypeScript,但你应该不能在同一个文件中使用 export (...)
和 export = (...)
。此外,当您将 export
添加到文件时,它会变成模块的声明文件,因此,最后,您将拥有一个默认导出命名空间的模块,然后您可以导入 Queues
来自 myLib
,而不是 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;
但是,无论如何,您都需要从 bull
和 myLib
导入。
我在 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'
根据文档,命名空间是一个全局变量,同名的命名空间将合并它们的导出接口。那么,如何从 @types/bull
合并命名空间 Bull
?谢谢!
嗯,事实是 @types\bull
并没有真正声明命名空间。
嗯,是的,只是把相关类型的列表归为一组,作为默认导出一起导出,所以,它真正导出的是namespace的contents ,而不是命名空间本身。这就是为什么您可以导入 Queue
,并使用 Queue
而不是 Bull.Queue
,如果 Queue
确实属于某个命名空间,您应该这样做。
此外,我不知道你使用的是什么版本的 TypeScript,但你应该不能在同一个文件中使用 export (...)
和 export = (...)
。此外,当您将 export
添加到文件时,它会变成模块的声明文件,因此,最后,您将拥有一个默认导出命名空间的模块,然后您可以导入 Queues
来自 myLib
,而不是 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;
但是,无论如何,您都需要从 bull
和 myLib
导入。