是否存在 TypeScript 错误?声明仅在以特定格式编写时有效

TypeScript bug, or not? Declaration only works when written in certain formats

在一个 .d.ts 声明文件中,我尝试用四种不同的方式做同样的事情,但只有两种方式有效:

// Doesn't work.
declare global {
    const THREE: typeof import('three')
}

// Doesn't work.
import * as _THREE from 'three'
declare const THREE: typeof _THREE

// Works.
import * as _THREE from 'three'
declare global {
    const THREE: typeof _THREE
}

// Works.
declare const THREE: typeof import('three')

'three' 模块包含 export namespace THREE

在前两种情况下,使用THREE作为全局的其他.ts文件会出现错误'THREE' refers to a UMD global, but the current file is a module. Consider adding an import instead.

对于这两种情况,使用 THREE 全局的其他 .ts 文件没有这样的错误,它们按预期使用了我对 THREE 的定义。

f.e.,如果我在 .d.ts 文件中使用第二个无效选项:

// globals.d.ts
import * as _THREE from 'three'
declare const THREE: typeof _THREE

然后在另一个 .ts 文件中:

// other-file.ts
console.log(THREE) // ERROR: 'THREE' refers to a UMD global, but the current file is a module. Consider adding an import instead.

但是如果我使用第四个(最后一个)选项,

// globals.d.ts
declare const THREE: typeof import('three')

那么另一个文件没有问题:

// other-file.ts
console.log(THREE) // no problem.

为什么前两个选项不起作用,而后两个选项起作用?

首先,让我说一下,鉴于此错误:'THREE' refers to a UMD global, but the current file is a module. Consider adding an import instead.,您实际上可能对 3.5 PR (although I see you commented on the associated issue 中的新编译器选项 allowUmdGlobalAccess 感兴趣,确保您没有错过修复)。

关于错误,这只是全局增强的工作方式与什么是模块和不是模块的交集:

  1. global只能在模块中使用,global在脚本文件中不需要
  2. 如果文件包含 importexport 语句,则它是一个模块,否则它被视为脚本文件。

根据这 2 个二进制规则,我们得到您描述的确切 4 种可能性

1.不是模块,global => 错误。

declare global {
    const THREE: typeof import('three')
}

由于该文件不是模块而是一个简单的脚本文件,使用 global 是错误的,因为在此文件中声明的任何内容无论如何都会在全局命名空间中,所以为什么要添加 global

2。模块,没有 global => 未使用的模块常量

    import * as _THREE from 'three'
    declare const THREE: typeof _THREE

因为这个文件包含一个 import 它是一个模块,所以声明的 const 无论如何都不在全局范围内,因此它只是一个不会被使用的模块局部变量。您在其他文件中遇到的错误来自 three 模块本身(它声明了一个 UMD 全局命名空间)

3。模块,带有 global

import * as _THREE from 'three'
declare global {
    const THREE: typeof _THREE
}

在这种情况下,文件是一个模块,但定义在 global 扩充中。这意味着 THREE 的定义将放在全局命名空间中,并且可以在其他文件中使用

4.不是模块,没有 global

declare const THREE: typeof import('three')

在最后一种情况下,文件不是模块,尽管是导入类型。只有 import 语句才能使文件成为一个模块,而 import 类型则不能。由于此文件不是模块,因此声明的 THREE 常量位于全局命名空间中,并可在其他文件中使用。

我也有这样的问题。

对于 tsconfig.json,您可以使用:

"compilerOptions": {
    "allowUmdGlobalAccess": true,

它使编译器可以访问 UMD 全局变量,列出了三种类型。所以你不需要在之后导入或引用它。与 JQuery 或 $.

相同