Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In a .d.ts declaration file, I tried to do the same thing in four different ways, but only two of them work:

// 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')

The 'three' module contains export namespace THREE.

In the first two cases, other .ts files using THREE as a global will have the error 'THREE' refers to a UMD global, but the current file is a module. Consider adding an import instead.

With the two cases that do work, other .ts files using the THREE global do not have such an error, and they use my definition of THREE as expected.

f.e., if I use the second non-working option in a .d.ts file:

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

then in another .ts file:

// 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.

But if I use the fourth (last) option,

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

then there's no problem in the other file:

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

Why do the first two options not work, but the last two do?

like image 789
trusktr Avatar asked Mar 04 '23 00:03

trusktr


2 Answers

Firstly, let me say that given this error: 'THREE' refers to a UMD global, but the current file is a module. Consider adding an import instead., you might actually be interested in the new compiler option allowUmdGlobalAccess in 3.5 PR (although I see you commented on the associated issue, making sure you didn't miss the fix).

Regarding the errors, this is just an intersection of how global augmentation works and what is and isn't a module:

  1. global can only be used in modules, global is not necessary in script files
  2. A file is a module if it contains an import or export statement otherwise it is considered a script file.

Given these 2 binary rules, we get the exact 4 possibilities you describe

1. Not a module, with global => error.

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

Since the file is not a module but a simple script file, using global is an error, since anything declared in this file would be in the global namespace anyway, so why add global ?

2. Module, without global => unused module constant

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

Since this file contains an import it is a module, so the declared const is not in any way in the global scope and thus it's just a module local variable that will go unused. The error you are getting in other files is from the three module itself (which declares a UMD global namespace)

3. Module, with global

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

In this case the file is a module, but the definition is in a global augmentation. This mean that the definition of THREE will be put in the global namespace and will be available in other files

4. Not a module, no global

declare const THREE: typeof import('three')

In this last case, the file is not a module in spite of the import type. Only import statements make the file a module, import types do not. Since this file is not a module the THREE constant declared is in the global namespace and available as such in other files.

like image 106
Titian Cernicova-Dragomir Avatar answered Mar 06 '23 22:03

Titian Cernicova-Dragomir


I also have such kind of issue. Link

With your tsconfig.json you could use:

"compilerOptions": {
    "allowUmdGlobalAccess": true,

It gives compiler access to UMD globals, THREE types is listed. So you do not need to import or reference it after. Same like JQuery or $.

like image 43
Mikhail Kh Avatar answered Mar 06 '23 22:03

Mikhail Kh