TypeScript 3.1 namespace namespace
Comments:0 · Reading: 808 · Like: 0
- Provide basic articles and code examples
- Namespaces
- Separation into multiple files
- IV. Aliases
- 5. Use other JavaScript Libraries
- 6. Sample Code
Naming Note: The term name has changed in TypeScript 1.5. "Internal module" is now called "namespace" and "external module" is now abbreviated as "module" in order to be consistent with ES6 terminology, that is, module X {equivalent to the current namespace X{
Provide basic articles and code examples
The following code will be used throughout the article, mainly a few simple string validators, which can be used to validate user input in the form or to validate external data:
All validators are placed in one file:
// All validators are in one file interface StringValidator { isAcceptable(s: string): boolean; } let lettersRegexp = /^[A-Za-z]+$/; let numberRegexp = /^[0-9]+$/; class LettersOnlyValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } class ZipCodeValidator implements StringValidator { isAcceptable(s: string) { return s.length === 5 && numberRegexp.test(s); } } // Some simple tests let strings = ["Hello", "8288", "123"]; let validators: { [s: string]: StringValidator; } = {}; validators['ZIP code'] = new ZipCodeValidator(); validators['Letters only'] = new LettersOnlyValidator(); for (let s of strings) { for (let name in validators) { let isMatch = validators[name].isAcceptable(s); console.log(`'${ s }' ${ isMatch ? "matches" : "does not match" } '${ name }'.`); } }
The results of compiler compilation are as follows:
// All validators are in one file var lettersRegexp = /^[A-Za-z]+$/; var numberRegexp = /^[0-9]+$/; var LettersOnlyValidator = /** @class */ (function () { function LettersOnlyValidator() { } LettersOnlyValidator.prototype.isAcceptable = function (s) { return lettersRegexp.test(s); }; return LettersOnlyValidator; }()); var ZipCodeValidator = /** @class */ (function () { function ZipCodeValidator() { } ZipCodeValidator.prototype.isAcceptable = function (s) { return s.length === 5 && numberRegexp.test(s); }; return ZipCodeValidator; }()); // Some simple tests var strings = ["Hello", "8288", "123"]; var validators = {}; validators['ZIP code'] = new ZipCodeValidator(); validators['Letters only'] = new LettersOnlyValidator(); for (var _i = 0, strings_1 = strings; _i < strings_1.length; _i++) { var s = strings_1[_i]; for (var name_1 in validators) { var isMatch = validators[name_1].isAcceptable(s); console.log("'" + s + "' " + (isMatch ? "matches" : "does not match") + " '" + name_1 + "'."); } }
Operation results:
Namespaces
There are only two validators above. With the increase of validators, we need a way to organize the code so that we can record their types without worrying about naming conflicts with other objects. Therefore, we wrap validators in a namespace instead of putting them in a global namespace.
In the following example, all validator-related types are placed in a namespace called Validation, because we want these interfaces and classes to be accessible outside the namespace, so we need to use export.
Conversely, variables lettersRegexp and numberRegexp do not need to be exported in detail, so they are not accessible outside the namespace. In the test code at the end of the file, it's better than accessing outside the namespace, so you need to qualify the name of the type, such as Validator. Letters OnlyValidator.
Verifier using namespaces
// Verifier using namespaces namespace Validator { export interface StringValidator { isAcceptable(s: string): boolean; } const lettersRegexp = /^[A-Za-z]+$/; const numberRegexp = /^[0-9]+$/; export class LettersOnlyValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } export class ZipCodeValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } } // test let strings = ['Hello', '89772', '1230']; let validators: { [s: string]: Validator.StringValidator; } = {}; validators['ZIP code'] = new Validator.ZipCodeValidator(); validators['Letters Only'] = new Validator.LettersOnlyValidator(); for (let s of string) { for (let name in validators) { console.log(`"${ s }" - ${ validators[name].isAcceptable(s) ? "matches" : "does not match" } ${ name }`); } }
Compiled results:
// Verifier using namespaces var Validator; (function (Validator) { var lettersRegexp = /^[A-Za-z]+$/; var numberRegexp = /^[0-9]+$/; var LettersOnlyValidator = /** @class */ (function () { function LettersOnlyValidator() { } LettersOnlyValidator.prototype.isAcceptable = function (s) { return lettersRegexp.test(s); }; return LettersOnlyValidator; }()); Validator.LettersOnlyValidator = LettersOnlyValidator; var ZipCodeValidator = /** @class */ (function () { function ZipCodeValidator() { } ZipCodeValidator.prototype.isAcceptable = function (s) { return lettersRegexp.test(s); }; return ZipCodeValidator; }()); Validator.ZipCodeValidator = ZipCodeValidator; })(Validator || (Validator = {})); // test var strings = ['Hello', '89772', '1230']; var validators = {}; validators['ZIP code'] = new Validator.ZipCodeValidator(); validators['Letters Only'] = new Validator.LettersOnlyValidator(); for (var _i = 0, string_1 = string; _i < string_1.length; _i++) { var s = string_1[_i]; for (var name_1 in validators) { console.log("\"" + s + "\" - " + (validators[name_1].isAcceptable(s) ? "matches" : "does not match") + " " + name_1); } }
You can see that after using NameSpace, Validator actually assigns two properties through an immediate execution function.
Separation into multiple files
As applications grow larger and larger. We need to separate the code into different files for easy maintenance.
Multi-file namespace
Now divide the above Validator into multiple files, although they are different files, but they are still the same namespace and are used as if they were the top one in a file.
Because there are dependencies between different files, a reference tag is added to tell the compiler the association between files.
validation.ts
namespace Validation { export interface StringValidator { isAcceptable(s: string): boolean; } }
LettersOnlyValidator.ts
/// <reference path="Validation.ts" /> namespace Validation { const lettersRegexp = /^[A-Za-z]+$/; export class LettersOnlyValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } }
ZipCodeVlidator.ts:
/// <reference path="Validation.ts" /> namespace Validation { const numberRegexp = /^[0-9]+$/; export class ZipCodeValidator implements StringValidator { isAcceptable(s: string) { return s.length === 5 && numberRegexp.test(s); } } }
Test.ts
/// <reference path="Validation.ts" /> /// <reference path="LettersOnlyValidator.ts" /> /// <reference path="ZipCodeValidator.ts" /> // Some samples to try let strings = ["Hello", "98052", "101"]; // Validators to use let validators: { [s: string]: Validation.StringValidator; } = {}; validators["ZIP code"] = new Validation.ZipCodeValidator(); validators["Letters only"] = new Validation.LettersOnlyValidator(); // Show whether each string passed each validator for (let s of strings) { for (let name in validators) { console.log(`"${ s }" - ${ validators[name].isAcceptable(s) ? "matches" : "does not match" } ${ name }`); } }
When it comes to multiple files, you have to ensure that all compiled code is loaded in two ways:
The first way to compile all input files into one output file is to use the -- outFile tag
tsc --outFile sample.js Test.ts
Compiled results:
/// <reference path="Validation.ts" /> var Validation; (function (Validation) { var lettersRegexp = /^[A-Za-z]+$/; var LettersOnlyValidator = /** @class */ (function () { function LettersOnlyValidator() { } LettersOnlyValidator.prototype.isAcceptable = function (s) { return lettersRegexp.test(s); }; return LettersOnlyValidator; }()); Validation.LettersOnlyValidator = LettersOnlyValidator; })(Validation || (Validation = {})); /// <reference path="Validation.ts" /> var Validation; (function (Validation) { var numberRegexp = /^[0-9]+$/; var ZipCodeValidator = /** @class */ (function () { function ZipCodeValidator() { } ZipCodeValidator.prototype.isAcceptable = function (s) { return s.length === 5 && numberRegexp.test(s); }; return ZipCodeValidator; }()); Validation.ZipCodeValidator = ZipCodeValidator; })(Validation || (Validation = {})); /// <reference path="Validation.ts" /> /// <reference path="LettersOnlyValidator.ts" /> /// <reference path="ZipCodeValidator.ts" /> // Some samples to try var strings = ["Hello", "98052", "101"]; // Validators to use var validators = {}; validators["ZIP code"] = new Validation.ZipCodeValidator(); validators["Letters only"] = new Validation.LettersOnlyValidator(); // Show whether each string passed each validator for (var _i = 0, strings_1 = strings; _i < strings_1.length; _i++) { var s = strings_1[_i]; for (var name_1 in validators) { console.log("\"" + s + "\" - " + (validators[name_1].isAcceptable(s) ? "matches" : "does not match") + " " + name_1); } }
The compiler automatically sorts the output according to the reference tags in the source code, or specifies each file separately.
tsc --outFile sample.js Validation.ts LettersOnlyValidator.ts ZipCodeValidator.ts Test.ts
Compiled results:
In the second way, you can compile every file (by default, see the screenshot above). Each source file will generate a JavaScript file, and then introduce all Javascript files in the correct order through the < script > tag on the page, such as:
<script src="Validation.js" type="text/javascript" /> <script src="LettersOnlyValidator.js" type="text/javascript" /> <script src="ZipCodeValidator.js" type="text/javascript" /> <script src="Test.js" type="text/javascript" />
IV. Aliases
Another simplified namespace operation is to use import q = x.y.z to give a short name to commonly used objects. Don't confuse the original load module import x = require('name') grammar, which creates an alias for the specified symbol.
You can use this method to create aliases for any identifier, including objects in the imported module:
// alias namespace Shapes { export namespace Polygons { export class Triangle { } export class Square { } } } import polygons = Shapes.Polygons; let sq = new polygons.Square(); // Same as "new Shapes.Polygons.Square()"
After compilation:
// alias var Shapes; (function (Shapes) { var Polygons; (function (Polygons) { var Triangle = /** @class */ (function () { function Triangle() { } return Triangle; }()); Polygons.Triangle = Triangle; var Square = /** @class */ (function () { function Square() { } return Square; }()); Polygons.Square = Square; })(Polygons = Shapes.Polygons || (Shapes.Polygons = {})); })(Shapes || (Shapes = {})); var polygons = Shapes.Polygons; var sq = new polygons.Square(); // Same as "new Shapes.Polygons.Square()"
Note that instead of using the require keyword, you import the qualified name assignment of the symbol directly. This is similar to var, but it also applies to types and imported symbols with namespace meanings. Importantly, for values, import generates references that are different from the original symbol, so changing the VaR value of the alias does not affect the value of the original variable.
5. Use other JavaScript Libraries
To describe the types of class libraries that are not written by TypeScript, you need to declare the API s exported by the class libraries. Since most libraries provide only a few top-level objects, namespaces are a good way to represent them.
We call it a declaration because it is not a concrete implementation of an external program. We usually write these statements in.d.ts. If you are familiar with C/C++, you can use it as an. h file.
External namespaces
The popular library D3 defines its functions in global object d3. Because the library is loaded through a script tag (not through a module loader), its declaration file uses internal modules to define its type. In order for the TypeScript compiler to recognize its type, we use an external namespace declaration. For example:
declare namespace D3 { export interface Selectors { select: { (selector: string): Selection; (element: EventTarget): Selection; }; } export interface Event { x: number; y: number; } export interface Base extends Selectors { event: Event; } } declare var d3: D3.Base;
6. Sample Code
This article's sample code:
Copyright of articles: Postbird-There I am , in the world more exciting!
Links to this article: http://www.ptbird.cn/typescript-namespace.html
Reprinted please indicate the original source of the article!