A generic type is defined when a function, interface, or class is defined without specifying its parameter types, which are determined only when passed in at run time. The argument type is a variable, usually represented by a capital letter T, but you can also use other characters, such as U, K, etc.

Syntax: add a suffix to a function, interface, or class name:

function generic<T> () {}
interface Generic<T> {}
class Generic<T> {}
Copy the code

I met a generic

Generics are used because they help us reuse the same code for different types of input.

For example, write the simplest function that returns any value passed to it:

// If the number type is passed:
function identity(arg: number) :number {
    return arg
}

// If a string is passed in:
function identity(arg: string) :string {
    return arg
}
Copy the code

Using generics, you can unify two functions:

// Add the type variable T, which captures the type passed in by the user (e.g. : number) and acts as the return value type
function identity<T> (arg: T) :T {
  return arg
}
Copy the code

The return type of a generic function depends on your business needs. It is not necessary to return T:

// The type of the input parameter is unknown, but the String type is returned by the String conversion
function identity<T> (arg: T) :string {
  return String(arg)
}
Copy the code

Multiple type parameters

A generic function can define multiple type parameters separated by commas

:
,>

function extend<T.U> (first: T, second: U) :T & U {
  for(const key in second) {
    (first as T & U)[key] = second[key] as any
  }
  return first as T & U
}
Copy the code

The default type of a generic parameter

Function parameters can define default values, and generic parameters can define default types

The default parameter syntax is:

function min<T = number> (arr:T[]) :T{
  let min = arr[0]
  arr.forEach((value) = >{
     if(value < min) {
         min = value
     }
  })
   return min
}
console.log(min([20.6.8n])) / / 6
Copy the code

Generic types and generic interfaces

// Function type:
// (x: number, y: number) => String indicates the function type
const add: (x: number, y: number) = > string = function(x: number, y: number) :string {
  return (x + y).toString()
}

// Generic type:
function identity<T> (arg: T) :T {
  return arg
}

      
       (arg: T) => T is a generic type
      
let myIdentity: <T>(arg: T) = > T = identity
{
      
       (arg: T): T}
      
let myIdentity: { <T>(arg: T): T } = identity
Copy the code

Generic interfaces:

interface GenericIdentityFn {
  <T>(arg: T): T
}
function identity<T> (arg: T) :T {
  return arg
}
let myIdentity: GenericIdentityFn = identity
Copy the code

By treating the generic parameter as a parameter to the entire interface, we can prepopulate the generic parameter to the interface name. So we know exactly which generic type to use:

interface GenericIdentityFn<T> {
  (arg: T): T
}
function identity<T> (arg: T) :T {
  return arg
}
let myIdentity: GenericIdentityFn<number> = identity
Copy the code

When using a generic interface, a type parameter is passed to specify the generic type

A generic class

Find the smallest heap class of type number:

class MinClass {
  public list: number[] = []
  add(num: number) {
    this.list.push(num)
  }
  min(): number {
    let minNum = this.list[0]
    for (let i = 0; i < this.list.length; i++) {
      if (minNum > this.list[i]) {
        minNum = this.list[i]
      }
    }
    return minNum
  }
}
Copy the code

Need to support string types, need generics:

// Class name with 
      
class MinClass<T> {
  public list: T[] = []
  add(num: T) {
    this.list.push(num)
  }
  min(): T {
    let minNum = this.list[0]
    for (let i = 0; i < this.list.length; i++) {
      if (minNum > this.list[i]) {
        minNum = this.list[i]
      }
    }
    return minNum
  }
}

let m = new MinClass<string>()
m.add('hello')
m.add('world')
m.add('generic')
console.log(m.min()) // generic
Copy the code

Generic constraint

Syntax: Generic constraints are implemented through the extends keyword.

interface User {
  username: string
}
// Constraints that the input parameter user must contain the username attribute
function info<T extends User> (user: T) :string {
  return 'imooc ' + user.username
}
Copy the code
type Args = number | string 
// constraints that the generic parameter T inherits from the type Args (a combination of number and string)
class MinClass<T extends Args> {}
const m = new MinClass<boolean>() / / the Error, must be number | type string
Copy the code

Multitype generic constraints

The generic constraint for multiple types is implemented using the

syntax:

interface Sentence {
  title: string,
  content: string
}

interface Music {
  url: string
}
// constrain the generic argument T to inherit from the cross type Sentence & Music
// This allows you to access parameters of both interface types
class Classic<T extends Sentence & Music> {
  private prop: T

  constructor(arg: T) {
    this.prop = arg
  }

  info() {
    return {
      url: this.prop.url,
      title: this.prop.title,
      content: this.prop.content
    }
  }
}
Copy the code

Learning links

  • www.imooc.com/wiki/typesc…