泛型

作者: 0说 | 来源:发表于2024-02-15 20:18 被阅读0次
    // 创建泛型函数:
    
    // 1.语法:在函数名称的后面添加<>(尖括号),尖括号中添加类型变量,比如此处的Type。
    // 2.类型变量 Type,是一种特殊类型的变量,它处理类型而不是值。
    // 3.该类型变量相当于一个类型容器,能够捕获用户提供的类型(具体是什么类型由用户调用该函数时指定)
    // 4.因为 Type 是类型,因此可以将其作为函数参数和返回值的类型,表示参数和返回值具有相同的类型
    // 5.类型变量 Type,可以是任意合法的变量名称
    function aFn<Type>(value: Type): Type {
      return value
    }
    console.log(aFn<string>('55')) // string 类型
    console.log(aFn<number>(555)) // number 类型
    
    // 简化调用泛型函数
    // 1.在调用泛型函数时,可以省略<类型>来简化泛型函数的调用
    // 2.此时,TS 内部会采用一种叫做类型参数推断的机制,来根据传入的实参自动推断出类型变量Type 的类型
    // 3.比如,传入实参10,TS 会自动推断出变量num 的类型number,并作为 Type 的类型。
    aFn(10)
    
    // 泛型约束:
    // 默认情况下,泛型函数的类型变量Type 可以代表多个类型,这导致无法访问任何属性。比如,id('a')调用函数时获取参数的长度:
    function bFn<T>(value: T): T {
      console.log(value.length) // 参数可多种类型 有这里如果是数字类型会报错
      return value
    }
    bFn(555)
    
    // 添加泛型约束收缩类型,主要有以下两种方式:1指定更加具体的类型2添加约束
    function cFn<T>(value: T[]): T[] { // 指定更加具体的类型
      console.log(value.length)
      return value
    }
    cFn('444') // 报错 因为我们上面指定了是[]
    cFn([]) // 没报错
    
    // extends 添加约束
    interface ILength {length: number}
    function dFn<T extends ILength>(value: T): T { // 这里的 extends 不是继承 是 传入的类型参数一定要length 属性
      console.log(value.length)
      return value
    }
    dFn(555) //类型“number”的参数不能赋给类型“ILength”的参数
    dFn('555') // string 有lenght属性 ∴没报错
    dFn([]) // array 有lenght属性 ∴没报错
    
    泛型约束
    function getProp<T, K extends keyof T>(obj: T, key: K): void{
      console.log(obj[key])
    }
    interface ObjType {age: number, name: string}
    const Obj = {age: 66, name: 'james'}
    getProp<ObjType, 'age'>(Obj, 'age') // 第二个参数只能 Obj的key
    getProp<ObjType, 'name'>(Obj, 'name')
    getProp<ObjType, 'name3'>(Obj, 'name3') // 报错
    
    泛型接口
    interface Atype<T> {
      id: (n: T) => T
      ids: (n: T) => T[]
    }
    // 用的时候要指定 某个类型 不能没有
    const obj:Atype<number> = {
      id(n){
        return n
      },
      ids(n){ return [n] }
    }
    console.log(obj.id(5))
    console.log(obj.ids(5))
    
    const obj2:Atype<string> = {
      id(n){
        return n
      },
      ids(n){ return [n] }
    }
    console.log(obj2.id('5'))
    console.log(obj2.ids('5'))
    
    泛型接口数组应用
    泛型类
    class Geral<T> {
      defaultValue: T
      constructor(val: T) {
        this.defaultValue = val
      }
      add(val: T): T {
        this.defaultValue = val
        return val
      }
    }
    const geral = new Geral<number>(6)
    console.log(geral)
    geral.add('666') // 这里也可能传number 因为在实例的时候已经指定了number类型的
    
    const geral2 = new Geral(6) // 也可以不用指定具体的类型 里面 constructor 有做赋值  TS会自动推断 constructor Geral<number>(val: number): Geral<number>
    
    
    内置工具 partial内置工具
    interface Props {
      id: number,
      name: string
    }
    type Props2 = Partial<Props> // 把接口传进去 会实现出所有的属性为可选的 类型出来 type Props2 = { id?: number | undefined;name?: string | undefined;}
    let aObj: Props = { // 类型 "{ id: number; }" 中缺少属性 "name",但类型 "Props" 中需要该属性
      id: 5555
    }
    
    let bObj: Props2 = { // 没有报错
      id: 5555
    }
    console.log(aObj,bObj)
    
    只读类型
    interface Props {
      id: number,
      name: string
    }
    type Props2 = Readonly<Props> // 实例出来新的类型里面的属性都为只读
    let obj:Props2 = {
      id: 666,
      name: 'james'
    }
    obj.id = 666 // 无法为“id”赋值,因为它是只读属性
    
    Pick工具
    interface Props {
      id: number,
      name: string
    }
    type Props2 = Pick<Props, 'id'> // 实例出来新的类型 type Props2 = {id: number;}
    let obj:Props2 = {id: 5555, name: '666'} // 对象字面量只能指定已知属性,并且“name”不在类型“Props2”中
    
    Record工具
    type Atype = Record<'aa' | 'bb', string>  // 相当于 type Atype = {aa: string; bb: string;}
    let obj:Atype = {
      aa: '555',
      bb: '55'
    }
    
    索引签名类型
    interface AnyType  {
      [key: string]: number
    }
    const obj: AnyType = {
      id: 5555,
      aaa: 9999,
      bbb: '555' // 报错 不能将类型“string”分配给类型“number”
    }
    console.log(obj)
    
    数组索引类型
    interface ArryType<T>  {
      [n: number]: T
    }
    const arr: ArryType<number> = [0, 1, 2]
    console.log(arr)
    
    映射类型
    type KeyType = 'aaa' | 'bbb' | 'ccc'
    type KeyType2 = {
      ddd: number
      fff: number
    }
    type PorpType = { [key in KeyType] : number } // 循环 KeyType type PorpType = { aaa: number;bbb: number;ccc: number;}
    type PorpType2 = { [key in KeyType2] : number } // 不能循环 KeyType2 不能将类型“KeyType2”分配给类型“string | number | symbol”
    const obj:PorpType = {
      aaa: 5,
      bbb: 5,
      ccc: 5,
    }
    console.log(obj)
    
    keyof
    type KeyType = {
      ddd: number
      fff: number
    }
    type PorpType = { [key in keyof KeyType] : number } // keyof 把 KeyType 变成 'ddd' | 'fff' 才能被in循环
    const obj:PorpType = {
      ddd: 5,
      fff: 5
    }
    console.log(obj)
    
    T[P]使用
    type KeyType = {
      ddd: number
      fff: string
    }
    type PorpType = KeyType['ddd'] // 访问KeyType ddd 类似于对象访问 type PorpType = number
    // 多个属性名
    type PorpType2 = KeyType['ddd' | 'fff'] // 访问KeyType ddd 类似于对象访问 type PorpType = number | string
    // 使用keyof
    type PorpType3 = KeyType[keyof KeyType] // type PorpType3 = string | number
    

    相关文章

      网友评论

          本文标题:泛型

          本文链接:https://www.haomeiwen.com/subject/pngsadtx.html