The most difficult thing in typescript is undoubtedly generics, so what is the motivation for generics
Think about a question: How did generics appear and what problems did it solve
Now there is an echo method, which passes in what type of value and returns what type of value
function echo(arg) { return arg } const result = echo(123)
The return value of result is an any type, which is not in line with our expectations. Then the types of specified input and output parameters are also not in line with our expectations. In this case, generic types are used
Generics
definition
- When defining a function, interface or class, you do not specify a specific type in advance, but specify a specific type when using it
use
- Add a pair of angle brackets after the function name, and the generic name in the angle brackets (habitually written as T, which can be any name),
- The generic name can be seen as a variable (or as a placeholder)
- Generics can be any type and can be specified when used
// Insert angle brackets after the function name, write the generic name T, and the parameters and return types are t function echo<T>(arg:T):T { return arg } const str: string = 'character string' // result is of type string const result = echo(str) // You can also not specify the type, and ts can automatically infer the type const result = echo(123) // The result is of type number
Now there is a tuple with two different types of values. Pass this tuple into the swap method, exchange the positions of the two values, and return the tuple after the exchange position
// According to the above requirements, we can realize // Define tuples const tuple:[number,string] = [123,'str'] // Implementation of swap method function swap<T,U>(tuple:[T,U]):[U,T] { return [tuple[1],tuple[0]] } // call const result = swap(tuple)
result[0]. Methods that can call strings
result[1]. You can call the method of number
Constrained generics
The following method outputs arg Length there is a wavy line under length, and an error has occurred
The following figure suggests that generic T does not necessarily contain the attribute length, so static type checking will report an error
Then the parameter accepted by this function should be the parameter with the length attribute. Use the extends keyword to restrict the incoming generics
Use extends to make the incoming value meet the constraints
// First, define an IWithLength interface interface IWithLength { length: number } // Use the extends keyword after the generic name T to inherit the defined IWithLength interface function echoWithLength<T extends IWithLength>(arg:T):T { console.log(arg.length) return arg } // Under verification const str = echoWithLength(`str`) const obj = echoWithLength({a:1,b:'str'}) const arr = echoWithLength([1,2,3])
Using generics to describe classes
Create a new queue class, implement two methods, enter the queue and leave the queue. At this time, you can use the generic class
// Generic type passed after class name class Queue <T>{ private data:T[] = []; push(item:T) { return this.data.push(item) } pop():T { this.data.shift() } } // When instantiating, pass in the desired type const queue1 = new Queue<number>() queue1.push(1) console.log(queue1.pop().toFixed()) // The return type here is number. You can use the number method // When instantiating, pass in the desired type const queue2 = new Queue<string>() queue1.push(`str`) console.log(queue2.pop().length) // At this time, you can call the method of string
Use generics to describe objects
// Dynamically specify values when defining types interface KeyPair<T,U> { key: T; value: U; } let kp1: KeyPair<number,string> = { key: 123, value: 'str' } let kp2: keypair<string,number> = { key: 'str', value: 123 }
Use generics to describe arrays
Define an array of type number
// Method 1 let arr2: Array<number> = [1,2,3] // Method 2 interface Info { age: number name: string } let arr1: Info[] = [ {age: 18, name: 'lili'}, {age: 10, name: 'hihi'}, ]
Using generics to describe functions
// Define a generic interface interface IPlus<T> { (a:T,b:T) : T } // Variable binding type const plus: Iplus<number> = function (a,b){ return a + b; } // number type const a:Iplus<number> = plus(1,2) // string type const b:IPlus<string> = plus('hello','wold')