TS decorators, Mixins, modules and namespaces

Table of contents

decorator

Definition of a decorator

class decorator

Mixins

Modules and Namespaces

Modules in TS

Namespaces in TS

decorator

The main role of a decorator is to extend some new behavior to an existing method or class, rather than modifying it directly.

After ES2015 enters Class, when we need to share or extend some methods or behaviors between multiple different classes, the code will become complicated and extremely inelegant, which is an important reason why decorators are proposed . But ECMAScript's decorator proposal has not yet been finalized, so let's learn about decorators in TypeScript. However, in TS, decorators are still an experimental feature and may change in the future, so if you want to use decorators, you need to enable experimentalDecorators in the build configuration of tsconfig.json and set it to true:

"experimentalDacorators":true

Definition of a decorator

A decorator is a special type of declaration that can be attached to a class, method, accessor, property or parameter. add with @

The decorator is essentially a function and has been widely used in other languages.

For example: python, but still a beta version in TS, to enable the experimental decorators feature, you must enable the experimental Decorators compiler option on the command line or in tsconfig.json:

  • Add to the class, class decorator

  • Added to the method, the method decorator

  • Add to the accessor, the accessor decorator

  • Add to the property, property decorator

  • Add to the parameter, parameter decorator

class decorator

  • Class decorators are declared just before the class declaration

  • Class decorators are applied to class constructors and can be used to observe, modify or replace class definitions

  • Class decorators cannot be used in declaration files (.d.ts) nor in any external context (like declare)

  • A class decorator expression is called at runtime as a function with the class's constructor as its only parameter

  • If the class decorator returns a value, it replaces the declaration of the class with the provided constructor

  • Class decorator, which does not change the original content of the class, but dynamically adds content to it

export default{}

// define decorator
//First define a function, and then this function has a parameter, which is the target to be decorated. The role of the decoration is different, and the target represents different things. After defining this function, it can be used as a decorator, in the form of @function name, written in front of the content to be decorated.
// keyword function name (struct: property type)
function testDecorator(constructor:any){
    constructor.prototype.uname="Xue Zhiqian"
    constructor.prototype.show=()=>{
        console.log(`I am handsome: ${constructor.prototype.uname}`);
        
    }
}
@testDecorator
class Person{

}
let p = new Person();
(p as any).show()

function factory class decorator

function testDecorator(flag:boolean){
    if(flag){
        return function(constructor : any){
            constructor.prototype.uname="Xue Zhiqian"
            constructor.prototype.show=():void =>{
                console.log(`I am handsome: ${constructor.prototype.uname}`);
            }
        }
    }else{
        return function(constructor : any){
            constructor.prototype.show=():void =>{
                console.log(`Hello World`);
                
            }
        }
    }
}
@testDecorator(true)
class Person{

}
let p = new Person();
(p as any).show()

Mixins

Introduction: In addition to traditional object-oriented inheritance, a popular way to create classes from reusable components is to combine the code of another simple class. You're probably already familiar with mixins and their features in languages ​​like Scala, but it's also very popular in JavaScript.

Function: Solve the problem of inheritance in TS - only one class can be inherited at a time

Note: class mixins cannot mix property names

export default{}

let nameObj = {name:"G.E.M"}
let ageObj = {age:20}
Object.assign(nameObj,ageObj)
console.log(nameObj);
console.log(ageObj);

Modules and Namespaces

Modules in TS

Typescript modules are designed with the idea of ​​organizing code that can be replaced.

The relationship between two modules is established by using import and export at the file level

Modules use module loaders to import other modules. At runtime, the role of the module loader is to find and execute all dependencies of the module before executing the module's code. The most well-known JavaScript module loaders are CommonJS for Node.js and Require.js for Web applications.

Module export uses the keyword export keyword, the syntax format is as follows:

//File name:modular

export interface modular{

// code part

}

To use the module in another file, use the import keyword to import it:

import Test = require("./modular")

import Test = require("./modular")

export class UserInfo implements Test.Person{
    name="G.E.M";
    age=18
    sex="Female"
    show(){
        console.log("Hello");
        
    }
}
let p = new UserInfo()
console.log(p);
console.log(p.name);

// import {obj} from "./modular";
// console.log(obj);

Namespaces in TS

In the process of project development, we will find out that our naming is strictly standardized. We cannot choose the name arbitrary, but if we use the standard method to name as much as possible, we will inevitably cause pollution. The TypeScript provide namespace to avoid this problem occurred before TS1.5 and was called an internal module. It was mainly used to organize code and avoid naming conflicts

  • The essence is to define a large object and put all variables/methods/classes/interfaces in it

  • export via export

  • Defined by namespace

// namespace A{
//     export const a = 100;
// }
// namespace B{
//     export const b = 200;
// }
// console.log(A.a);
// console.log(B.b);

// nested namespace
namespace B{
    export const b = 1000
    export namespace C{
        export const c = 2000
    }
}
console.log(B.b);
console.log(B.C.c);

// Simplified namespace
import c =B.C.c
console.log(c);

// main file
// Import namespaces from other files
import {D} from "./namespace"
console.log(D.d);


//code in namespace
export namespace D{
    export const d = 10000
}

Tags: Javascript Front-end TypeScript

Posted by axiom82 on Tue, 13 Sep 2022 21:04:14 +0300