TS: How to use generics

TS: Generic

1 Introduction

  • Sometimes, if we want to make the parameters and return types of a function the same, we can use type variables .

  • A type variable is a special type of variable used to represent a type rather than a value.

    function identity<T>(arg : T) : T{
          
          
        return arg;
    }
    
  • After the generic function is defined, it can be used in two ways.

  • One is to pass in all parameters, including type parameters:

    let out = identity<string>("yivi");
    
  • The other is to use type inference-that is, the compiler will automatically infer the type:

    let out = identity("yivi");
    
  • Type inference helps us keep the code simple and highly readable.

2. Generic variables

  • Let's take a look at an example:

    function foo<T>(arg : T): T{
          
          
        console.log(arg.length);	// error,arg的类型为T,无明确指示方法,因此报错。
        return arg;
    }
    
  • When we want to manipulate an array of type T, .lengththe property exists, so no error will be reported:

    function foo<T>(args : T[]):T[]{
          
          
        console.log(args.length);
        return args;
    }
    
    // or
    
    function foo<T>(args : Array<T>) : Array<T>{
          
          
        console.log(args.length);
        return args;
    }
    

3. Generic types

  • We can use different generic parameter names, as long as the number and usage are consistent;

  • You can also use object literals with call signatures to define generic functions;

    function identity<T>(arg : T) : T{
          
          
        return arg;
    }
    
    let myIdentity : <U>(arg : U) => U = identity;
    
    // or 
    
    let myIdentity : {
          
          <T>(arg : T):T} = identity;
    
  • Take the object literal above and write it as an interface:

    interface IdentityInterface{
          
          
        <T>(arg : T) : T;
    }
    
    function identity<T> (arg : T) : T{
          
          
        return arg;
    }
    
    let myidentity : IdentityInterface = identity;
    
  • It is also possible to treat a generic parameter as a parameter of the entire interface, so as to ensure that we know which generic type is being used:

    interface IdentityInterface<T>{
          
          
        (arg : T) : T;
    }
    
    function identity<T> (arg : T) : T{
          
          
        return arg;
    }
    
    let myidentity : IdentityInterface<string> = identity;
    
  • Generic classes are similar to generic interfaces, and both use <> for constraints:

    class Foo<T>{
          
          
        state : T;
        add : (x : T, y : T) => T;
    }
    
    let myfoo = new Foo<number>();
    myfoo.state = 1;
    myfoo.add = (x,y)=>{
          
          
        return x + y;
    }
    

4. Generic constraints

  • In the above example, we mentioned .lengththat if this attribute is used on generics, an error will be reported;

  • Therefore, we only need to implement an interface and let the generic type have this attribute to prevent the compiler from reporting errors;

    interface Length{
          
          
        length : number;
    }
    
    function identity<T extends Length>(arg : T) : T{
          
          
        console.log(arg.length);
        return arg;
    }
    
  • Although the compiler will not report an error, if you use a type without this attribute, it will also report an error;

  • So we need to pass in a value that meets the constraints and contains the necessary attributes;

    identity({
          
          length : 10,value : 100});
    

5. Use class types in generics

  • When using generics to create factory functions in TypeScript, you need to refer to the class type of the constructor.

    function create<T> (c : {
          
          new() : T}) : T{
          
          
        return new c();
    }
    
    class Foo{
          
          
        name : string;
    }
    
    let a : Foo = create(Foo);
    a.name = 'yivi'
    console.log(a.name)
    

Guess you like

Origin blog.csdn.net/yivisir/article/details/109560081