TypeScript learning: IX. generics of TypeScript

Posted by mandrews81 on Fri, 29 Oct 2021 18:46:37 +0200

Definition of generics

  Generics,   In the process of software development, we should not only create consistent and well-defined APIs,   Reusability should also be considered.   Components can support not only current data types, but also future data types, which provides you with very flexible functions when creating large systems.
 
In languages like C# and java, generics can be used to create reusable components,   A component can support multiple data types. This allows users to use components with their own data types.
 
  In popular understanding, generics is the solution   class   Interface   Method reusability, and support for unspecified data types
 

Generic Functions

There is a requirement: pass in the specified parameter type and return the specified parameter type     For example, if the parameter type is required to be string, return string    The parameter type is required to be number, and number is returned

// Only return string Function of
function getData(val:string):string{
return val + "Return string";
}
//  Only return number Function of
function getData1(val:number):number{
    return val; // Return number
}

 

  Two functions are used here to practice the function. If you need to return    Is it necessary to add another function to implement bloolean type, which will lead to code redundancy

  Some people will think of using any type to implement functions,

function getData2(val:any):any{
    return 123; // return number
}
getData2("string");

The function can be implemented with any, but there will be such errors. I pass in string type and return number, which does not meet the requirements. In addition, using any type is to abandon the original intention of typeScript and type checking

Use generics to solve problems: generics can support unspecified types, and the implementation requires that the incoming type is consistent with the returned type

 // T Represents a generic type. The specific type is determined when calling
function getData<T>(val:T):T{
    return val;
}
// Call:
// number Type, return number type
getData<number>(100);

// string type
getData<string>("Zhang San");

getData<boolean>(123); // Wrong writing definition Boolean Type, cannot be passed in number Parameters of type

 

  If a function is required to return a generic function that must be of type string:

 // Generic function, specifying return string type
function getData<T>(val:T):string{
    return val + "val";
}

getData<number>(234);

getData<string>("Zhang San");

 

Through these two examples, we can see that generic T represents a data type. The specific data type is determined by passing in the specified type when calling the method.  

  getData<T>       getData<string>       All t's in this function are generic  

Generic class

Requirements: for example, there is a minimum heap algorithm,   You need to support both return number and string types,    Implemented through the generics of classes
// Not applicable to the writing of generic classes
class MinClass{
    public list:number[] = [];

    add(num:number):void{
        this.list.push(num);
    }
    min():number {
        var minNum = this.list[0];
        for(var i = 0; i < this.list.length; i++) {
            if(minNum > this.list[i]) {
                minNum = this.list[i];
            }
        }
        return minNum;
    }
}

var m = new MinClass();
m.add(2);
m.add(50);
m.add(1);
console.log(m.min());  // Output: 1

  This column can implement the minimum heap algorithm of number type. For type verification, the type of string cannot be used

Look at the implementation of generic classes

// Generic class
class MinClass<T>{
    public list:T[] = [];

    add(num:T):void{
        this.list.push(num);
    }
    min():T {
        var minNum = this.list[0];
        for(var i = 0; i < this.list.length; i++) {
            if(minNum > this.list[i]) {
                minNum = this.list[i];
            }
        }
        return minNum;
    }
}

var m = new MinClass<number>(); // Instantiate the class and specify the generic type as number
m.add(2);
m.add(50);
m.add(1);
console.log(m.min());  // Output: 1

var s = new MinClass<string>();
s.add("n");
s.add("a");
s.add("z");
console.log(s.min());  // Output: a    Code value calculation

Using generics, you can write number and string types  

 

---Generic class - Advanced

Requirement: define a class and take the class as a parameter to restrict the incoming data type

Implementation: define a user class, which is used to map database fields,   Then define a mysqlDb class to operate the database, and then pass the user class as a parameter to mysqlDb for execution

// Entity classes that map database fields
class User{
    public username:string | undefined;
    public pasword:string | undefined;

    constructor() {

    }
}

// Database operation type
class MysqlDb{
    // Add data
    add(user:User):boolean{
        return true;
    }
    // Delete data
    // Modify data
    // ----
}

var u = new User();
u.username = "Zhang San";
u.pasword = "123";

var Db = new MysqlDb();

Db.add(u);  // Take this user Add to database

 

  this   MysqlDb can perform operations such as adding user class. The same problem: this MysqlDb can only operate on user class. If I have other tables:

 

class ArticleCate{
    title:string | undefined;
    desc:string | undefined;
    status:number | undefined;
    constructor() {

    }
}
// Database operation type
class MysqlDb{
    // Add data
    add(info:ArticleCate):boolean{
        console.log(info);
        return true;
    }
    // Delete data
    // Modify data
    // ----
}
var art = new ArticleCate();
art.status = 1;
art.desc = "home news";
art.title = "domestic";
var Db = new MysqlDb();
Db.add(art);  // Take this ArticleCate Add to database

Does this lead to code redundancy? If there are multiple entity classes to operate, multiple must be defined    MysqlDb to implement

Let's see how generics are implemented   MysqlDb   Just once

// Entity classes that map database fields
class User{
    public username:string | undefined;
    public pasword:string | undefined;

    constructor() {

    }
}

class ArticleCate{
    title:string | undefined;
    desc:string | undefined;
    status:number | undefined;
    constructor() {

    }
}

var art = new ArticleCate();
art.status = 1;
art.desc = "home news";
art.title = "domestic";
var DbArt = new MysqlDb<ArticleCate>(); // Direct instantiation mysqlDb
DbArt.add(art);  // Take this ArticleCate Add to database

var user = new User();
user.username = "Zhang San";
user.pasword = "24123";
var DbUser = new MysqlDb<User>();
DbUser.add(user); // Take this User Add to database
// DbUser.add(123); // Wrong writing, with type verification

 

Therefore, generics can represent not only basic data types, but also defined classes

 

generic interface

Let's first look at a function interface

 // Function interface
interface ConfigFn{
    (val: string, val2: string):string;
}
// Implementation interface
var getData:ConfigFn = function(val1:string, val2:string):string{
    return val1 + val2;
}

var str:string = getData("Zhang San", "Li Si");

console.log(str);

 

  Let's look at generic interfaces

 // Generic function interface
interface ConfigFn{
    <T>(val: T, val2: T):T;
}
// Implementing generic function interfaces
var getData:ConfigFn = function<T>(val1:T, val2:T):T{
    return val1;
}

var str:string = getData<string>("Zhang San", "Li Si");

console.log(str);

 

  When implementing a generic interface, the generic type is not specified, and the type is specified when calling

Another way to write

// Another way to write generic function interfaces
interface ConfigFn<T> {
    (val: T, val2: T):T;
}

// Define function
function getData<T>(val1:T, val2:T):T{
    return val1;
}
// Implementation interface, And specify the type
var myGetData:ConfigFn<string> = getData; 

myGetData("Zhang San", "Li Si");

Note: implementing a generic interface should also be a generic interface

 

 

With generics, when calling methods, the same code can be used by multiple types, which greatly expands the reusability of the code  

 

Topics: Javascript TypeScript