Definition of generics
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
// 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