This is an article that should have been summarised before the holidays, but I was too lazy and salty, so BALabalabala (omitted tens of thousands of words for reasons). But the truth always only one, that is, the more is an excuse, just the insufficient of the holidays, it is time for accepting heart, as a new, sprout and consolidate together under the summary before the TS of the generic knowledge, to output a bear a new money and you will understand, can control the basis of the generic knowledge articles, probably through the following three points to illustrate

  • Use generics in functions
  • Use generics in classes
  • Use generics in interfaces

Use generics in functions

Use generics in functions – Case 1

So let’s take a look at this piece of code

function join(a: number | string, b: number | string) {
  return `${a} ${b}`;
}
Copy the code

This is a very water code, as a new also can be seen, a and B can pass a string as well as a number, the final return value, is using the string template to spell the two, where we pass the value of the four possibilities

  • A number B number
  • A string B string
  • A digit B Character string
  • A Character string B number

But the end result is still concatenation, and there’s a requirement that we have to have the same type of the two variables, and I’m going to erase the class, what’s going on here, and I’m going to pull out the generic, rewrite the code and use it like this

function join<T> (a: T, b: T) {
  return `${a} ${b}`;
}

join<number> (1.2);
join<string> ('1'.'2');
// join
      
       (1, '2'); // The string 2 is a number
      
// join
      
       (1, '2'); // The number 1 is a string
      
Copy the code

The most basic way to use it is to specify the type of the argument by enclosing Angle brackets before the parentheses of the method execution (you can omit the Angle brackets, ts does type inference, but this is not recommended). This also restricts the type of the argument

Use generics in functions – Case 2

We can also constrain the type of each item in an array, such as writing a simple function that passes in an array and returns the array

function getArr<T> (arr: T[]) {
  return arr;
}

getArr<number> ([1.2.3]) // If "number" is specified, each entry in my array must also be "number", otherwise an error is reported
getArr<string> (['g'.'q'.'f']) // Again, string is specified
Copy the code

Use generics in functions – Case 3

Obj [key]; obj[key]; obj[key]

function getVal<T> (obj: T, k: keyof T){
  return obj[k];
}

interface Person {
  name: string;
  age: number;
}

getVal<Person>({
  name: 'gqf'.age: 29
}, 'age') // The key can only be passed as name or age, otherwise an error will be reported
Copy the code

Use generics in functions – Case 4

In fact, our first example can be modified to have to concatenate numbers and strings, using the syntax of multiple generics

function manyTest<K.V> (a: K, b: V) {
  return `${a} ${b}`
}

manyTest<number.string> (1.'2') // The generics specify that the first argument is a number and the second argument is a string, so the corresponding argument should be passed the same way
Copy the code

Use generics in classes

Let’s simulate such a scenario and design our hero skills!

Use generics in classes – version one

The initial version was simple. Instead of generics, we wrote a random class, passed in an array of four skills, and had a method to get them

class DesignHero {
  constructor(private skills: string[]){}

  getSkill (index: number) {
    console.log(this.skills[index])
    return this.skills[index]; }}const hero = new DesignHero(['q'.'w'.'e'.'r']) // string[] so we pass in an array of strings
hero.getSkill(3)
Copy the code

Use generics in classes – version two

We usually like to use numbers to illustrate skills, such as one, two, three skills, so we will change this time, using numbers array

class DesignHero {
  constructor(private skills: number[]){} // Change the number from string[] to number[]

  getSkill (index: number) {
    console.log(this.skills[index])
    return this.skills[index]; }}const hero = new DesignHero([1.2.3.4]) // number[] so we pass in an array of numbers
hero.getSkill(3)
Copy the code

Use generics in classes – version three

The way of writing death is a little silly, we didn’t learn the basic knowledge of generics in front of it, then quickly use generics to modify the case

class DesignHero<T> {
  constructor(private skills: T[]){}

  getSkill (index: number) {
    console.log(this.skills[index])
    return this.skills[index]; }}const heroNumberSkill = new DesignHero<number> ([1.2.3.4]) // Generics good generics bar, I can specify the use of numbers as skill description
heroNumberSkill.getSkill(1)
const heroStringSkill = new DesignHero<string> (['q'.'w'.'e'.'r']) // Generics good generics bar, I can specify to use string as skill description
heroStringSkill.getSkill(2)
Copy the code

Use generics in classes – version 4

Generics also can use inheritance, for instance can only accept string or number < T extends string | number >, specific code is as follows

class DesignHero<T extends string | number> { / / if the inheritance string | number into a Boolean, for example, the following must be an error
  constructor(private skills: T[]){}

  getSkill (index: number) {
    console.log(this.skills[index])
    return this.skills[index]; }}const heroNumberSkill = new DesignHero<number> ([1.2.3.4])
heroNumberSkill.getSkill(1)
const heroStringSkill = new DesignHero<string> (['q'.'w'.'e'.'r'])
heroStringSkill.getSkill(2)
Copy the code

Use generics in classes – version 5

The final version, which is the generic inheritance interface, allows us to specify that each item in an array must be an object in a specified format

interface Skill {
  name: string;
  canDamage: boolean; // Is it a direct damage ability
}

class DesignHero<T extends Skill> { // Specifies the Skill for each item in the array, following the format of the interface, with the name and canDamage fields
  constructor(private skills: T[]){}

  getSkillName (index: number) {
    console.log(this.skills[index].name)
    return this.skills[index].name; }}const finalHero = new DesignHero([
  {
    name: 'One skill'.canDamage: true}, {name: 'Two Skills'.canDamage: false}, {name: Three skills.canDamage: false}, {name: 'Four skills'.canDamage: true,
  }
])

finalHero.getSkillName(0)

Copy the code

Use generics in interfaces

Finally, we will learn about generics in the interface to simulate the request response scenario. The initial code is as follows

interface IResponseData{
    code: number; message? :string;
    data: any;
}
async function getData(url: string){
  let response = await fetch(url);
  let data = await response.json();
  return data;
} 
Copy the code

The code above is clearly have a problem, we will find the interface of the data item not sure the specific format of different interface will return data is not the same, when we want to according to the specific interface to return the request specific data format, is in trouble, because you call getData is not clear what is the specific interface, What is the corresponding data? At this point we can use generics for IResponseData. The complete code is as follows

interface IResponseData<T>{
    code: number; message? :string;
    data: T;
}

// User interface
interface IResponseUserData{
    id: number;
    username: string;
    email: string;
}

// Article interface
interface IResponseArticleData{
    id: number;
    title: string;
    author: IResponseUserData; 
} 

async function getData<U> (url: string){
    let response = await fetch(url);
    let data: Promise<IResponseData<U>> = await response.json(); // Note that we return a Promise, and then specify different data formats for different interfaces
    return data;
} 

(async function(){
    let userData = await getData<IResponseUserData>('/user');
    userData.data.username;

    let articleData = await getData<IResponseArticleData>('/article'); articleData.data.author.email; }) ()Copy the code

conclusion

In fact it seems nothing to summarize, after all is the basic knowledge, basic mentioned in this article, also if there are any errors or omissions, welcome leaders correct, let sprouting new I continue to strengthen (isn’t it too skin ha ha), finally I wish you all enjoy the holiday, the work after the holiday and fishing in the smooth. This is Merio Piggy, thank you for your support