There are some unique concepts in typescript that need to describe what has changed in the JavaScript object type. For example, the most unique concept is "declaration merging". Understanding this concept will be helpful for you to use typescript development in your current JavaScript project. It also opens the door to understanding more advanced abstract concepts.
For the purposes of this article, declaration merging refers to the work of the compiler to merge two identically named declarations into a single declaration. The combined declaration has two attributes of the original declaration. Of course, the declaration is not limited to merging two declarations, and the number of claims that need to be consolidated can be arbitrary (note: they have the same name).
Basic concepts
In typescript, a declaration can have three cases: namespace/Module (namespace: internal module; module: External module), type, value. When the declaration is to create a namespace/module, the namespace is available through the dot symbol (.). To access. Creating a declaration of a type creates a type that specifies the name and structure. Finally, the declared values are those parts that are visible in the output JavaScript (for example, functions and variables).
Declaration Type |
Namespace |
Type |
Value |
Namespace |
X |
|
X |
Class |
|
X |
X |
Enum |
|
X |
X |
Interface |
|
X |
|
Type Alias |
|
X |
|
Function |
|
|
X |
Variable |
|
|
X |
Understanding what each statement creates will help you understand what merges when you perform a declaration merge.
Interface merging
The simplest and most common declaration merge is interface merging. At the bottom of the compilation, the declaration merge mechanism joins two declared members into an interface of the same name.
interface Box { height:number; Width:number;} Interface Box { scale:number;} var box:box = {height:5, width:6, scale:10};
The non-function members in the interface must be unique, and if two/more interfaces declare non-function members of the same name at the same time, the compiler throws an error.
For function members, a function member of the same name is considered an overload of the function. The value of the note is that interface A and subsequent interface a (here becomes a ') merge, the overloaded functions in interface a ' will have a higher precedence than the same function in interface A.
See Case study:
interface Document { createelement (tagname:any): Element;} Interface Document { createelement (tagname:string): HtmlElement;} Interface Document { "div"): htmldivelement; " Span "): htmlspanelement; " Canvas "): htmlcanvaselement;}
These three interfaces will be merged into a separate declaration. Note that the order within each set of interfaces remains the same, except that each group is merged and that the members of the subsequent interface are placed in front of the new declaration.
interface Document { "div"): htmldivelement; " Span "): htmlspanelement; " Canvas "): htmlcanvaselement; CreateElement (tagname:string): HtmlElement; CreateElement (Tagname:any): Element;}
Module merging
A module of the same name, similar to an interface, merges its members. Because the module creates a namespace and a value, we need to understand how they are merged.
When merging namespaces, the type definitions for the output interfaces declared by each module are merged, and namespaces with the same name are merged into a separate namespace that contains the merged interface.
When merging values, if a given name module already exists, then the output members in the subsequent module will be added to the module.
Take a look at the declaration merge of the animal module in this example:
Module Animals { Export class Zebra {}}module Animals { Export interface legged {numberoflegs:number;} Export class Dog {}}
Equivalent:
Module Animals { export interface legged {numberoflegs:number;} Export class Zebra {} Export class Dog {}}
This case is a good start to learning module merging, but for a more complete understanding, we also need to understand what happens to non-exporting Members. Non-exported members are only visible in the original (not merged) module. This means that after merging, the merged members from other claims cannot access the non-exported members.
We can look at a detailed explanation:
module Animal { vartrue; function Animalshavemuscles () { return havemuscles; }} Module Animal { function doanimalshavemuscles () { return Havemuscles; // <--Error, havemuscles cannot be accessed here }}
Because the Havemuscles member is not output, only the Animalshavemuscles function that shares the unincorporated module can access the symbol. Although the Doanimalshavemuscles function is part of the merged module, it still cannot access the non-output members of this other merged module with the same name.
Merging of modules with classes, functions, enumerations
The module is flexible enough to be merged with other types of declarations. The declaration of a module must follow the declaration it merges with. The final merged declaration will contain the properties of the two claim types. Typescript uses this feature to implement some JavaScript patterns.
The first module merges the case, and we merge the module with the class. This gives the user a way to describe the inner class:
class Album { Label:Album.AlbumLabel;} Module Album { export class albumlabel{ name:string; Show () { Console.log (this. Name); } Constructor (name:string) { this. Name = name; }} var New Album.albumlabel ("Ys"); Newalbum.show ();
The accessibility rules for a merged member are the same as the "module merge" in the previous section, so we must export the Albumlabel class so that the merged class can access it. The end result is that there is another class inside a class. You can also add more static members using the existing classes of the module.
class test{ fn:test.testfn}module Test { var value:string = "World"; Export Class testfn{ Show (name:string) { Console.log (name+ " " +Value); }}} var New test.testfn (); Newtest.show ("Hello");
In addition to the inner class pattern, you may be familiar with the practice of creating a function in JavaScript to extend its properties later. Typescript uses claims merging to achieve this purpose and ensures type safety.
function Buildlabel (name:string): string { return buildlabel.prefix + name + Buildlabel.suffix;} Module Buildlabel { var suffix = ""; var prefix = "Hello,";} Alert (Buildlabel ("Sam Smith");
Similarly, a module can be used to extend the static members of an enumeration:
enum Color {red= 1, Green= 2, Blue= 4}module Color {exportfunctionMixcolor (colorname:string) {if(ColorName = = "Yellow") { returnColor.Red +Color.green; } Else if(ColorName = = "White") { returnColor.Red + Color.green +Color.Blue; } Else if(ColorName = = "Magenta") { returnColor.Red +Color.Blue; } Else if(ColorName = = "Cyan") { returnColor.green +Color.Blue; }}}alert (Color.mixcolor ("Yellow"));
Not allowed to merge
In typescript, not all merges are allowed. So far, classes cannot be merged with classes, variables and classes cannot be merged, and interfaces and classes cannot be merged. To emulate the merging of classes, refer to the previous section: Typescript mixins (mixed)
TypeScript Declaration Merging (declaration merge)