A “name merge” is when the compiler combines two or more independent names of the same name that appear in multiple places in the program into a single name, which has all the characteristics of the original separate name.

Declarations in TypeScript create one of three entities: a namespace, a type, or a value.

  • The declaration to create a namespace creates a new namespace.
  • Create a type declaration: Use the declared model to create a type and bind it to the given name.
  • A declaration that creates a value creates the value that the JS will see on output.

Combined interface

This is the most common declaration merge in TS. The underlying merge mechanism is to put members of both parties in the same named interface.

interface Person {
  name: string;
}
interface Person {
  age: number;
  name: number; // error: Non-function members of the interface should be unique or of the same type.
}
class person implements Person {
  name: string = "";
  age: number = 18;
}
Copy the code

For a function member of an interface, each function with the same name is treated as an overload of that function. The priority rules for overloading are as follows:

  • The priority order of each group remains the same.
  • Subsequent interfaces have higher priority
  • This declaration is raised to the top when a function has an argument of type single string literals.
interface Person {
  like(sth: string) :string; / / 5
  like(sth: "dog") :any; / / 2
}
interface Person {
  like(sth: number) :number; / / 3
  like(sth: string[]) :string[]; / / 4
  like(sth: "cat") :any; / / 1
}

/ / after the merger
interface Person {
  like(sth: "cat") :any;
  like(sth: "dog") :any;
  like(sth: number) :number;
  like(sth: string[]) :string[];
  like(sth: string) :string;
}
Copy the code

Merge namespace

Namespace merge rules:

  • Exported members cannot be defined again, unlike interface merges.
  • Non-exported members are visible only within the original namespace. (Non-exported members cannot be accessed by members merged from other namespaces.)
namespace Animal {
  let haveMuscles = true;

  export function animalsHaveMuscles() {
    returnhaveMuscles; }}namespace Animal {
  export function doAnimalsHaveMuscles() {
    return haveMuscles; // Error, because haveMuscles is not accessible here}}/ / after the merger
namespace Animal {
  export function animalsHaveMuscles() {
    return haveMuscles;
  }
  export function doAnimalsHaveMuscles() {
    returnhaveMuscles; }}Copy the code

Namespaces are merged with class and function and enumeration types

Merging namespaces and classes allows us to represent inner classes or add static attributes to classes

class Person {}
namespace Person {
  export let id = 123123;
  export class Man {}}console.log(Person.id);
console.log(Person.Man);
Copy the code

Create a function and later extend it to add some properties.

function Func() {}
namespace Func {
  export let version = "1.0";
}
console.log(Func.version); / / 1.0
Copy the code

Similarly, you can extend enumerated types.

enum Color {
  Red,
}
namespace Color {
  export let yellow = "yellow";
  export function func() {}}console.log(Color); // {0: "Red", Red: 0, yellow: "yellow", func: ƒ}
Copy the code

Also note that when namespaces and classes and functions are merged, the namespace must be written after the class/function. Why?

When you compile to ES5, you’ll notice that when you declare enumerated types, you declare variables in advance, so you don’t need to declare functions in advance; Classes/functions, on the other hand, need to pass the function variable into the closure, so the function needs to be written first.

/ / class
var Person = / * *@class * / (function () {
  function Person() {}
  returnPerson; }) (); (function (Person) {
  Person.id = 123123;
  var Man = / * *@class * / (function () {
    function Man() {}
    returnMan; }) (); Person.Man = Man; })(Person || (Person = {}));/ / function
function Func() {},function (Func) {
  Func.version = "1.0";
})(Func || (Func = {}));

/ / the enumeration
var Color;
(function (Color) {
  Color[(Color["Red"] = 0)] = "Red";
})(Color || (Color = {}));
(function (Color) {
  Color.yellow = "yellow";
  function func() {}
  Color.func = func;
})(Color || (Color = {}));
Copy the code

conclusion

It is not recommended to have multiple declarations of the same name in the program. It is best to separate them into different modules. The declarative merge feature of TS is also designed to accommodate older design patterns, allowing ts to be used in older code and finding design flaws.

The TypeScript project family

  • Don’t use TypeScript? Namespace.
  • TS effort: declared merger
  • How do I introduce external class libraries into TypeScript?
  • Get started, tsconfig (file options)
  • Get started, tsconfig (compilation option)
  • Would you like to learn a more efficient way to build TS (engineering introduction)
  • TS compiler! From ts – loader to Babel
  • Code check tool! From TSLint to ESLint
  • TS single test tool! Ts – jest and Babel/jest