Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In TypeScript, what does it mean for an import or export to be "top-level"?

Tags:

typescript

The TypeScript docs say:

In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).

What does it mean for an import or export to be "top-level"?

like image 871
Dan B. Avatar asked Feb 16 '19 13:02

Dan B.


1 Answers

Top level import is a static import that is located at the very top of the file. However it's called "top-level" not because it is located at the top of the file, but because there are dynamic imports that are not top level:

import foo from 'foo' // top level import, static one

import('foo').then(/* ... */) // not top level import, dynamic one

// no static top-level import can live here (after any code that is not a top-level import declaration)

function bar() {
  import('foo').then(/* ... */) // not top level import, dynamic one
  // no static top-level import can live here
  // no export can live here too
}

// no static top-level import can live here

export const baz = 123 // exports are always top level, and static

// You still can add not top level imports here, in the very end
import('foo').then(/* ... */) 

Now, why this matters in Typescript?

Well if you put two files without a top-level import/export, that has two identifiers that are the same, you will get an error:

// a.ts
let foo = 1 // Error: duplicate identifier

// b.ts
let foo = 1 // Error: duplicate identifier

This happens because there are no top-level export/import declarations and TS considers these files to be scripts (in contrast to modules). And what happens if you load in a browser two scripts with same identifiers? Right, a "duplicate identifier" error will rise. Because both variables live in the global namespace.

Therefore, to avoid that you can do this:

// a.ts
let foo = 1 // Ok

// b.ts
let foo = 1 // Ok
export {} // This is the magic. b.ts is now a module and hence, is not polluting the global namespace.
like image 155
Nurbol Alpysbayev Avatar answered Sep 28 '22 15:09

Nurbol Alpysbayev