Namespace
Any internal module declared with the module keyword should be replaced with the namespace keyword.
First step
Define a simple string validator, assuming that you will use them to validate yoghurt input in the form or external data
interface StringValidator{ isAcceptable(s:string): boolean } let letterRegexp = /^[A-Za-z]+$/ let numberRegexp = /^[0-9]+$/ // Verification letter class LetterOnlyValidator implements StringValidator { isAcceptable(s: string) { return lettersRegexp.test(s); } } // Verification number class ZipCodeValidator implements StringValidator { isAcceptable(s: string) { return s.length === 5 && numberRegexp.test(s); } } let strings = ["Hello", "98052", "101"]; 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 }'.`) } }
Namespace
With the addition of more validators, we need a means to block code so that we can record their types without worrying about naming conflicts with other objects. Therefore, we wrap the validator in a namespace instead of in the global namespace
In the following example, we put all the verifier methods in a namespace called Validation. Because we want these interfaces and classes to be accessible outside the namespace, we need to use export. On the contrary, the variables lettersRegexp and numberRegexp are implementation details and do not need to be exported, so they cannot be accessed outside the namespace. In the test code at the end of the file, since it is accessed outside the namespace, it is necessary to qualify the name of the type, such as Validation.LettersOnlyValidator.
namespace Validation { 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 s.length === 5 && numberRegexp.test(s); } } } // Validators to use let validators: { [s: string]: Validation.StringValidator; } = {}; validators["ZIP code"] = new Validation.ZipCodeValidator(); validators["Letters only"] = new Validation.LettersOnlyValidator(); for (let s of strings) { for (let name in validators) { console.log(`"${ s }" - ${ validators[name].isAcceptable(s) ? "matches" : "does not match" } ${ name }`); } }
Detach to multiple files
As the application becomes larger and larger, we need to separate the code into different files for maintenance
Multi file namespace
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); } } }
ZipCodeValidator.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 }`); } }
alias
Another way to simplify namespace operations is to use import q = x.y.z to give commonly used objects a short name. Don't get confused with the import x = require('name ') syntax used to load the module. The syntax here is to create an alias for the specified symbol. You can use this method to create aliases for any identifier, including objects in the imported module.
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()"
How should I write a. d.ts file when importing a third-party library without. d.ts?
Use other js Libraries
In order to describe the types of class libraries that are not portable with typescript, we need to declare the API exported by the class library. 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 often write these statements in. d.ts.
External namespace
The popular library D3 defines its functions in the global object D3. Because this library passes through a
In order for the typescript compiler to recognize its type, we use an external namespace declaration.
d3.d.ts
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