TypeScript 中的“declare global”和“declare namespace global”有什么区别?

问题描述

我有一个全局声明文件,我必须在其中使用 import 语句,从而使其成为一个模块,因此为了公开全局类型,我必须在全局命名空间上声明它们。

首先我尝试了这个:

import { SomeType } from 'some-package';

declare namespace global {
  interface ShouldBeGlobal {}
}

这不会引发语法错误,但它不会像我期望的那样工作:接口 ShouldBeAGlobal 未在全局范围内公开。

然而,这是有效的,而且它无处不在:

import { SomeType } from 'some-package';

declare global {
  interface ShouldBeGlobal {}
}

为什么第一个不起作用?

解决方法

在第一个示例中,您没有向全局命名空间公开任何内容,因为您实际上是在创建一个名为 global 的新命名空间。确认这一点的一种简单方法是注释您的 import 语句,从而使您的声明文件成为全局声明文件(那些没有 import/export 的文件),并尝试访问global.ShouldBeGlobal—您会看到它可用。

第二种方式是将类型暴露到全局命名空间中的正确方式(真正的)。与上面类似,如果您想了解 namespace global 语句实际在做什么,您也可以将其更改为:

import { SomeType } from 'some-package';

declare global {
  interface ShouldBeGlobal {}

  // not that you don't need the declare keyword here again,because it's already nested on a declare block
  namespace global {
    interface AnotherInterface {}
  }
}

现在在任何文件中你应该仍然能够访问 ShouldBeGlobal 接口,但现在你也有 global.AnotherInterface,因为现在你在全局命名空间中创建了一个名为 global 的新命名空间.