Understanding generics in typescript? Application scenario?

The stars shine high 2021-09-15 08:53:45

 

 

One 、 What is it?

Generic programming (generic programming) It's a style or paradigm of programming language

Generics allow us to write code in a strongly typed programming language using types that we specify later , Indicate these types as parameters when instantiated stay typescript in , Defined function , Interface or class , Don't define specific types in advance , When used, a feature of a specified type

Suppose we use a function , It can accept a  number  Parameter and returns a number  Parameters , Write as follows :

function returnItem (para: number): number {
    return para
}

If we're going to accept one  string  type , And then back again  string type , It is written as follows :

function returnItem (para: string): string {
    return para
}

The above two writing methods , One of the most obvious problems is , Code repetition is relatively high

Although it can be used  any Type to replace , But this is not a good plan , Because our purpose is to receive what type of parameters and return what type of parameters , That is, we can only determine the type by passing in parameters at run time

In this case, you can use generics , As shown below :

function returnItem<T>(para: T): T {
    return para
}

You can see , Generics give developers the flexibility to create 、 The ability to reuse code

Two 、 Usage mode

Generics pass <> In the form of , It can be stated that :

  • function

  • Interface

  • class

Function declaration

The form of the declaration function is as follows :

function returnItem<T>(para: T): T {
    return para
}

When defining generics , You can define... At once 「 Multiple type parameters 」, For example, we can define generics at the same time  T  and Generic  U

function swap<T, U>(tuple: [T, U]): [U, T] {
    return [tuple[1], tuple[0]];
}

swap([7, 'seven']); // ['seven', 7]

Interface declaration

The form of interface declaration is as follows :

interface ReturnItemFn<T> {
    (para: T): T
}

So when we want to pass in a number As a parameter , You can declare the function like this :

const returnItem: ReturnItemFn<number> = para => para

Class declaration

When using generics to declare classes , It can act on the class itself , It can also act on member functions of classes

The following is a simple implementation of a stack structure with the same type of elements , As shown below :

class Stack<T> {
    private arr: T[] = []

    public push(item: T) {
        this.arr.push(item)
    }

    public pop() {
        this.arr.pop()
    }
}

Use as follows :

const stack = new Stacn<number>()

If the above can only pass  string  and  number  type , It can be used at this time  <T extends xx>  Guess the way to achieve 「 Constraint generics 」, As shown below :

 

 

In addition to the above form , The more advanced use of generics is as follows :

For example, to design a function , This function takes two arguments , One parameter is the object , Another parameter is the attribute on the object , We return the value of this property through these two parameters

At this time, it is designed that the generic index type and constraint type are implemented together

Index type 、 Constraint type

Index type  keyof T  Take out the attribute type of the incoming object to generate a union type , The generics here U Constrained in this union type , As shown below :

function getValue<T extends object, U extends keyof T>(obj: T, key: U) {
  return obj[key] // ok
}

Why generic constraints are needed above , Instead of directly defining the first parameter as  object type , Because by default  object  refer to {}, And the objects we receive are all kinds of , A generic type to represent the incoming object type , such as  T extends object

Use as shown in the figure below :

 

 

Multi type constraints

For example, you need to implement the type constraints of two interfaces as follows :

interface FirstInterface {
  doSomething(): number
}

interface SecondInterface {
  doSomethingElse(): string
}

You can create an interface to inherit the above two interfaces , as follows :

interface ChildInterface extends FirstInterface, SecondInterface {

}

The correct use is as follows :

class Demo<T extends ChildInterface> {
  private genericProperty: T

  constructor(genericProperty: T) {
    this.genericProperty = genericProperty
  }
  useT() {
    this.genericProperty.doSomething()
    this.genericProperty.doSomethingElse()
  }
}

The purpose of multi type constraints can be achieved through generic constraints

3、 ... and 、 Application scenarios

Through the above preliminary understanding , The following is written in  typescript  When , Defined function , Interface or class , Don't define specific types in advance , When using, when specifying a feature of a type , In this case, you can use generics

Flexible use of generics to define types , To master typescript  path

Please bring the original link to reprint ,thank
Similar articles

2021-09-15

2021-09-15

2021-09-15