日拱一卒:typescript泛型

78 阅读1分钟

前置知识

typescript类型遵循规则:先显式指定;无显式指定则进行推断。

进行推断的条件:

  1. 具有初始化值的变量
  2. 有默认值的函数参数
  3. 函数返回的类型

如果不满足推断条件,就会显示:具有隐式any类型。例如:变量没有初始化值;函数参数既没有显示指定,又没有默认值。

什么是泛型

泛型是类型参数化,用来约束类型成员之间的关系:

  1. 函数参数和返回值
  2. 类或接口成员和方法之间的关系

基础使用

约束函数参数类型

  1. 使用定义泛型参数,使用:T对函数参数进行指定
function fn<T>(params:T) {
    return params
}
  1. 也可以对返回值进行一些指定(虽然可以推断出来):
function fn<T>(params:T):T {
    return params
}
  1. 可以对函数参数的成员或者属性进行指定:
function fn<T>(params:T[]) {
    return params
}
// 调用
const arr = fn(['1',1])      // arr:string|number[]

调用方法

  1. 既可以自动推断,又可以手动指定
fn(10)  // 自动推断
fn<string>('hello') // 手动指定
  1. 指定两个或者多个
function fn<T, K>(a:T, b:k):T {
  console.log(b)
  return a
}
fn<string,number>('hello', 1)

动手实践

现在给定一个场景:手动实现lodash库里面的pick函数,用法示例如下:

import * as _ from 'lodash'

const obj = {
    a : 1,
    b : 'sdfa',
    c : [1,2,'1']
}

const newObj = _.pick(obj, 'a','c')
console.log(newObj)    

obj和newObj的类型分别为:

const obj: {  
a: number;  
b: string;  
c: (string | number)[];  
}
const newObj: Pick<{  
a: number;  
b: string;  
c: (string | number)[];  
}, "a" | "c">

代码:

const pick = function<T, K extends keyof T>(obj: T, pickArr: K[]) {
    return pickArr.reduce((newObj, key) => {
        if(Object.keys(obj).includes(key as string)) {
            newObj[key] = obj[key]
            return newObj
        }
    }, {} as Pick<T, K>)
}
const newObj = pick(obj, ['a', 'c'])