What is TypeScript generic programming

Keywords: Javascript Front-end TypeScript

Front end programmers may not know generics very well. They may know generics if they know Java, a strongly typed language. They can use generics to write dynamically reusable TS code. In TS, generics are generally used for classes, interfaces and functions.

Today, let's learn how to use generics in TypeScript and the scenarios where generics are usually used.

1. Quickly understand generics

Many front ends familiar with JS development may not understand what generics are. Let's understand generics through the simplest example.

The two functions are the same, but the input and return types are different. If you do not use generics in TS, you need to define two functions, but their types are different.

// Number type
function fun(args: number): number {
  return args;
}

// String type
function fun(args: string): string {
  return args;
}

Of course, you can use any type

function fun(args: any): any {
  return args;
}

But using any is actually avoiding type checking. Just like using JS, why use TS.

Let's use generics to implement it

2. Use generics

To create a generic Type, you need to use the Type parameter, which is generally defined with T or < T > to represent the data Type of a class, interface or function.

Let's rewrite the above function with generics

function fun<T>(args:T):T {
  return args;
}

Using generic functions is also simple

let result = fun<string>("Hello World");

Or so

let result2 = fun<number>(200);

We can run the code and verify it. We can go to the official playground

Address: https://www.typescriptlang.org/play

The above is the simplest use of generics in TS, which is often used.

Let's take a look at the slightly more complex usage of generics

3. Multiple types of generics

Above, we use T to represent a type. If a function has many parameters, we can use different letters to represent the type. Like the following

function fun<T, U, V>(args1:T, args2: U, args3: V): V {
  return args3;
}

The above function receives args1, args2 and args3, and returns args3. These parameters are not type qualified because T, U, V are used as generic types for function parameters.

Next, call this function

let result3 = fun<string, number, boolean>('Xiaoshuai', 23, false);

Then we run one to try

The function returns the third parameter, so it is false

Generics can be used not only for functions, but also for classes and interfaces. Let's continue

4. Create generic class

Similar to functions, the generic type of a class also uses the type parameters in < >, and then uses the < T > type to define methods and properties in the whole class.

Let's create a custom array class and define an arr array attribute. The type of the array is a generic type

class customArray<T> {
  private arr: T[] = [];
}

Create a method to get the array

getItems (): T[] {
  return this.arr;
}

Then create an addItem method to push elements into the array

addItem(item: T) {
  this.arr.push(item);
}

The type of arr array is T [], so our array can be of any type, such as number, string, Boolean, etc.

Next, add a removeItem method to delete the specified elements of the array

removeItem(item: T) {
  let index = this.arr.indexOf(item);
  if(index > -1) {
    this.arr.splice(index, 1);
  }
}

Now that the properties and methods of the class are almost written, let's test the results

let numObj = new customArray<number>();
numObj.addItem(10);

let strObj = new customArray<string>();
strObj.addItem('Xiaoshuai');

console.log(numObj);
console.log(strObj);

console.log(numObj.getItems());
console.log(strObj.getItems());

We created a numObj object of numeric type and a strObj object of string type

Let's take a look at some binding rules on generics

5. Generic constraints

Above, we learned how to use generics as types for functions and classes, but using generics also has some disadvantages, such as the following example

function getLength<T>(args: T) : number {
  return args.length;
}

In the above function, if the parameter passed in has the length attribute, it will work normally. If not, an error will be reported

We can see that the error is that generic T does not have a length attribute. What should we do

We can use a general constraint to create an interface named funcArgs and define the length attribute

interface funcArgs {
  length: number;
}

Now let's revise it

function getLength<T extends funcArgs>(args:T) : number {
  return args.length;
}

Now let's run

As you can see, TS will throw an exception when using a type without length parameter.

If the parameter has the length attribute, there will be no error messages.

summary

Today, we learned how to use generics in TypeScript, including applying generics to functions, classes, interfaces, etc.

If this article is helpful, wechat searches [Xiaoshuai's Programming Notes] for a little knowledge every day

Posted by iamyespee on Sat, 16 Oct 2021 11:11:37 -0700