I. namespace - namespace
If you are familiar with C++, Java, C#, etc., namespace should not be new to you. namespace can be used to encapsulate a piece of code, and code outside namespace cannot directly access the code inside namespace.
Namespaces are defined by the namespace
keyword. The format is as follows.
In the following example, _name
and getName
inside Lib
are not accessible outside the Lib
namespace.
If you use tsc
to compile the above code, the compiler will report an error directly.
Since JavaScript does not support namespace syntax, how does typescript implement namespaces? To understand how it works, first comment out the last two lines of code.
|
|
The contents of the compiled js file are as follows.
As you can see, the namespace principle is implemented through Immediately Execute Function (IIFE), where the function is executed and the variables inside the function are not available from the outside world (global scope).
In order to get the variables or functions inside namespace, you can expose the variables in namespace through the export
keyword and then access the exposed variables through namespace names .
Compiled with tsc
, the compilation passed and the compiled js file reads as follows.
You can see that the compiled code, by assigning the getName
function to Lib.getName
, implements the export
function, so you can access the variables inside the namespace from outside the namespace.
As you can see from the compiled js code, namespace is essentially an object, and we can access the variables inside the namespace through the properties of the object .
II. Exporting types and namespaces
As with modules, you can export type information from namespaces and access the exported types by the namespace name.
The compiled js code is as follows. The compiled js file does not contain any type information.
Namespaces can be nested and child namespaces can be exported by the parent namespace and then access the variables of the internal namespace through the namespace name chain.
The compiled js file is as follows.
III. Aliases
Because namespaces can be nested, when the embedding level is very deep, it is troublesome to access through namespace name chain, for example Space1.Space2.Space3.Space4.xxx
, you can simplify the namespace name chain by aliasing.
|
|
The above code simplifies access to MyLibA.Functions
by adding an alias to var API_FUNCTIONS = MyLibA.Functions;
.
But using the same approach, adding an alias to MyLibA.Types
will report an error because the MyLibA.Types
namespace only contains type information internally, no other fields exist, so it is essentially non-existent (the compiled JS code will remove the type information). You can use type Person = MyLibA.Types.Person
to simplify access.
TypeScirpt also supports using the import <alias> =
statement to simplify access to internal namespaces, and adding aliases to MyLib.Types
does not report an error, which is a syntactic sugar given to us by typescript to create aliases for namespaces.
|
|
IV. Importing Namespaces
Since a namespace is essentially an Object, you can import namespaces with the import statement.
|
|
To import namespaces, you need the execution environment of the code to support namespaces, the above example is ES Modules, if it is a NodeJS environment, which supports the CommonJS module system, then you need to use require
, exports
statements to import and export.
V. Modularity
Typescript provides //
, which works only during the ts compilation phase and is used to instruct the ts compiler to locate ts files.
|
|
/// <reference path="" />
is similar to #include
in the c language. It must appear at the top of the file and is essentially a comment, so it is only useful at the compile stage.
The value of the path
attribute specified by reference
is the path to another ts file, which is used to tell the compiler what dependencies the current file compiles with, somewhat similar to the import
statement, but without the need to import the specified variables.
When reference
specifies a file, typescript will automatically include this file in the compilation process when compiling, and all global variables within this file will be available in the current file (the file specified by reference
to exist).
As an example, in index.ts
, all global variables are obtained in the current file (the file specified by reference
) via /// <reference path=". /math.ts" />
introduces the math.ts
file.
Compiled by tsc index.ts
, after compilation there are two files index.js
and math.js
with the following contents.
Of course we can’t execute this code in the Node environment because it’s two separate files and there’s no require statement. We need to first package them into a single file bundle.js
and then execute it with the command node boundle.js
.
In the browser environment, we need to load the math.js
and index.js
files sequentially using the <script>
statement.
A better approach is to use the -outFile
configuration option of tsc
to package the output file into a bundle, and ts will automatically compile the file according to the reference
command.
Use the tsc --outFile bundle.js index.ts
command to compile the file, and the compiled bundle.js file will have the following contents.
VI. Extending namespaces
You can extend an already defined namespace using the reference
directive. Look directly at the following example.
In the b.ts
file, c.ts
is introduced via the reference
directive, which extends MyLibA
, adds the defaultPerson
variable, and all variables in MyLibA
are accessible in the b.ts
file, e.g. getPerson( 'John Doe', 21 );
In the a.ts
file, the b.ts
is introduced with the reference
directive, and the Person
, getPerson
and defaultPerson
members inside the namespace MyLibA
are accessible in the a.ts
file.
VII. Recommendations
This is the end of this chapter. namespaces are powerful, but if you ask me, when should I use namespaces? I would say, try to avoid namespaces and use the Modules system instead, now that Es Module is convenient, you can also use CommonJS instead of namespaces in node environments.
Namespaces came before ES Module, so maybe one day namespaces will be deprecated.