typescript的泛型

38 阅读3分钟

为什么要说泛型呢?最新看源码,刷帖的时候,看见一片哀嚎。特别是在工具库代码内部,成片成片的T, U等泛型,像雪花一样飘过来。都叫一个名称,整个代码里面一打岔,就不知道在看撒了。 em...老年人有记小笔记,断点的习惯,还能好一些。

为什么会有泛型

当我们写ts代码的时候,需要标注各种类型的数据。因为代码是一些逻辑内容的书面化的体现,内部是有一些规律的。CV大法在这种情况下是可以用的。 但是,当我们需要更改的时候。那就比较头疼了。当然你也可以提出这些类型,做对应的公共标注。 我们经常说,抽象化编程。当我们在公共的类型,总结基础的规律规则。 你会发现,它其中的一部分就是泛型。 被我们用来表示一类大概类型的类型。

ts 的泛型是什么

1.定义

它是一个高级类型。所谓高级类型是对比基础类型而言。 语义上它是一个广泛的类型。在定义之初泛指某一类的类型,尚未有实际的意义。 作为自定义的类型时,可以复用。

2.语法

以下使用泛型函数举🌰,示范语法

// 定义一个入参出参为同一个类型的函数
function demoFuc<T>(arg: T):T{
    return arg;
}

// 实际使用的时
const concatStr  = demoFuc<string>('hi') // 返回:hi

3.常用的泛型标识

我们看到代码中的泛型,其实常用的泛型为一些固定的类型,以下举🌰一些常用的

  • T 任意类型
  • K 对象中的键
  • V 对象中的值
  • E 表示枚举类型
  • A 表示数组类型中的元素类型
  • R 表示返回值类型
  • C 表示类的类型
  • F 表示函数类型

细心的小伙伴,应该发现规律了,大写的字母,代表了某些单词的首字母💡

泛型的基础使用场景

函数

泛型函数,在语法举例中已经说过了

接口的定义

inteface demoObj<T> {
    [key: string]: T;
}

// 定义

const aObj: demoObj<string> = {a: '1', b: '2'};

const aArr: demoObj<{a: string}> = {b: {a: '1'}};

成片的泛型场景

成片的泛型大军准备袭来,请准备接招

约束

缩小泛型可定义使用的范围,让泛型更加准确

function getProp<T, K extends keyof T>(obj: T, key: K): T[K] {
    return obj[key];
}

// 表示:返回值只能为 obj 对象内存在的 key

类型别名

类型一般用于多类型指定。举🌰

比如:现在需要有多个tooltip按钮,按钮的tool为按钮text内容

interface IButtonsProps<T> {
    data: T[] | T
}

type typeProps = {
    name: string;
    text: string;
    tip: string;
}

const Btns = (props: IButtonsProps<typeProps>) => {
    const { data } = props;
    const isSingleBtn = useMemo({
        return !Array.isArray(data) && data.text
    }, [data])
    return (
        isSingleBtn 
            ? 
            <btn tip={data.tip}>{data.text}</btn> 
            : 
            data.map(
                (item: item) => 
                    (<btn key={item.name} tip={item.tip}>{item.text}</btn>))
     )
}

默认值

可以为常用的类型,赋值默认类型。

请脑补正常赋值默认值的方式,方式相同。

不赘述。

其他

正常使用TS编码过程中,个人建议还是写人能看得懂的代码,合适的时候加上必要的注释。 除却之上的使用方式,还有根据不同条件,逻辑推断出来的泛型。

我们需要在合适的时候,减少冗余代码的编写,保持简洁,可读性。

结束了