In the TypeScript series :(3) declare merging

Declaration merging is the merging of two or more independent declarations into a single declaration that has all the features of each of the previous declarations.

[toc]

1. Basic Concepts

In TS, a declaration creates an entity of one of three types:

  • Namespaces: Use a namespace to declare a namespace. The declaration of a namespace creates a namespace and a value.

  • Type: The declaration of a type usually uses the interface or type keyword and gets a type. In addition, the declaration of the class and enum keywords also gets a type.

  • Values: Usually var, let, const are used to declare a variable and create a value. In addition, the class, enum, and function keywords also declare a value.

As can be seen, the namespace declaration creates a namespace and a value; Variable declarations create only one value; Interface and type declarations create only one type; Class and enum declarations create both a value and a type with the same name.

Second, the mergerinterfaceinterface

The merge of interfaces is the simplest and most common declaration merge. Declare multiple interfaces with the same name, and TS automatically merges them. However, if there is a non-functional field of the same name in these interfaces, the corresponding type of the field should also be the same; otherwise, it will be marked as an error.

interface A {
  name: string.age: number,}interface A {
  // Field name with the same name, corresponding to the same type,
  name: string.gender: 1 | 2,}interface B {
  name: string.age: number,}interface B {
  // An error was reported with the same name as the field age, corresponding to different types, respectively number and string
  age: string.gender: 1 | 2,}Copy the code

In interface merging, functions with the same name are treated as overloads of the same function, and the interface declared later has higher priority.

interface Cloner {
  clone(animal: Animal): Animal;
}
interface Cloner {
  clone(animal: Sheep): Sheep;
}
interface Cloner {
  clone(animal: Dog): Dog;
  clone(animal: Cat): Cat;
}
Copy the code

The three declarations are merged into the following declarations. The internal order of each declaration remains the same, but the subsequent declarations are first in each declaration.

interface Cloner {
  clone(animal: Dog): Dog;
  clone(animal: Cat): Cat;
  clone(animal: Sheep): Sheep;
  clone(animal: Animal): Animal;
}
Copy the code

There is one exception, however: when there is a parameter in the function signature that is of type single string literals (not joint literals), the signature is placed first.

// Three separate declarations
interface Document {
  createElement(tagName: any): Element;
}
interface Document {
  createElement(tagName: "div"): HTMLDivElement;
  createElement(tagName: "span"): HTMLSpanElement;
}
interface Document {
  createElement(tagName: string): HTMLElement;
  createElement(tagName: "canvas"): HTMLCanvasElement;
}

// will be merged into the following declaration
interface Document {
  createElement(tagName: "canvas"): HTMLCanvasElement;
  createElement(tagName: "div"): HTMLDivElement;
  createElement(tagName: "span"): HTMLSpanElement;
  createElement(tagName: string): HTMLElement;
  createElement(tagName: any): Element;
}
Copy the code

Three, merging,namespaceThe namespace

Similar to interface merging, the namespace of a declaration merges the members of each declaration. Since namespaces create namespaces and values, namespaces and values are merged.

Declare two separate namespaces
namespace Animals {
  export class Zebra {}}namespace Animals {
  export interface Legged {
    numberOfLegs: number;
  }
  export class Dog {}}// will be merged into:
namespace Animals {
  export interface Legged {
    numberOfLegs: number;
  }
  export class Zebra {}
  export class Dog {}}Copy the code

In the namespace declaration, members that are not exported cannot be obtained from another namespace with the same name, nor can they be accessed using the namespace name.

// Name is not exported by export
namespace Person {
  let name = "cc"
  export function getName(){
    return name
  }
}

namespace Person {
  export function setName(str: string){
    // Error, cannot get
    name = str
  }
}
Copy the code

In the above chestnut, the name is not exported in the first namespace, so the name cannot be retrieved in the second namespace. You only need to export to share this member in other namespaces with the same name.

// Name is not exported by export
namespace Person {
  export let name = "cc"
  export function getName(){
    return name
  }
}

namespace Person {
  export function setName(str: string){
    name = str
  }
}
Copy the code

Four,NamespacesClassesFunctionsEnumsmerge

1. Merge namespaces and classes

Members exported in a namespace become static members of the class with the same name, while members not exported cannot be retrieved by the class.

class Album {
  label: Album.AlbumLabel;
}
namespace Album {
  export class AlbumLabel {};
  export const name = "cc";
  let age = 18;
}

Album.name  // "cc"
Album.age  / / an error

const album = new Album()
album.name  // Error reported, no instance
Copy the code

2. Merge namespaces and functions

Members exported from a namespace become properties of functions of the same name.

function logName(str: string){
  console.log(str + logName.name)
}

namespace logName {
  export const name = "cc"
  export const age = 18
  let gender = 1
}

logName("yy")
Copy the code

3. Merge namespaces and enumerations

Merging namespaces and enumerations makes the exported members of the namespace an extension of the enumeration.

enum Color {
  red = 1,
  green = 2,
  blue = 4,}namespace Color {
  export function mixColor(colorName: string) {
    if (colorName == "yellow") {
      return Color.red + Color.green;
    } else if (colorName == "white") {
      return Color.red + Color.green + Color.blue;
    } else if (colorName == "magenta") {
      return Color.red + Color.blue;
    } else if (colorName == "cyan") {
      returnColor.green + Color.blue; }}export const pink = 10
}

Color.mixColor("yellow")  / / 3
Color.pink  / / 10
Copy the code

There are also module extensions and global extensions, which are not covered here. Next, let’s talk about enumerating Enums.