• TypeScript(7)泛型


    泛型

    指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。

    引入

    下面创建一个函数, 实现功能: 根据指定的数量 count 和数据 value , 创建一个包含 countvalue 的数组 不用泛型的话,这个函数可能是下面这样:

    1. function createArray(value: any, count: number): any[] {
    2. const arr: any[] = []
    3. for (let index=0; index < count; index++) {
    4. arr.push(value)
    5. }
    6. return arr
    7. }
    8. const arr1 = createArray('a', 3)
    9. const arr2 = createArray(1, 3)
    10. console.log(arr1)
    11. console.log(arr2)
    12. console.log(arr1[0].toFixed(), arr2[0].split(''))

    我们创建了一个函数createArray,传入2个参数valuecount,返回any类型的数组,然后定义了一个any类型的空数组arr。接下来我们查看结果
    在编译阶段我们没有报错是因为,我们把value设置为了any类型,但是当编译完成后运行时,arr1是字符串,字符串是没有toFixed方法的,所以会报错,那么我们希望在编译阶段就报错,就可以使用泛型

    使用泛型

    1. // 使用函数泛型
    2. function createArray<T>(value: T, count: number): T[] {
    3. const arr: Array<T> = []
    4. for (let index=0; index < count; index++) {
    5. arr.push(value)
    6. }
    7. return arr
    8. }
    9. const arr1 = createArray<number>(11, 3)
    10. console.log(arr1[0].toFixed())
    11. const arr2 = createArray<string>('AA', 3)
    12. console.log(arr2[0].split(''))
    13. console.log('---------')
    14. console.log(arr2[0].toFixed()) // 报错,因为字符串没有toFixed方法
    15. console.log(arr1[0].split('')) // 报错,因为number没有split方法

    泛型的意思就是类型由用户自己决定,比如function createArray<T>(value: T, count: number): T[],函数createArrayvalue参数和返回类型都由用户自己决定。const arr1 = createArray<number>(11, 3)这句代码是没问题,因为规定了number类型,传入的也是number
    当我们将代码修改成如下代码:
    我们发现报错了,因为规定了number类型,传入的却是字符串11
    当我们输入如下代码,也会报错
    报错原因如下
    所以如果我们使用了泛型,就会避免类型输入错误或者用错方法

    多个泛型参数的函数

    一个函数可以定义多个泛型参数

    1. function swap <K, V> (a: K, b: V): [K, V] {
    2. return [a, b]
    3. }
    4. const result = swap<string, number>('abc', 123)
    5. console.log(result[0].length, result[1].toFixed())

    泛型接口

    1. interface IbaseCRUD <T> {
    2. // 定义泛型数组data
    3. data: T[]
    4. add: (t: T) => void
    5. getById: (id: number) => T
    6. }
    7. class User {
    8. id?: number;
    9. name: string;
    10. age: number;
    11. constructor(name, age) {
    12. this.name = name;
    13. this.age = age;
    14. }
    15. }
    16. class UserCRUD implements IbaseCRUD<User> {
    17. data: User[] = []
    18. add(user: User): void {
    19. user = {...user, id: Date.now()}
    20. this.data.push(user)
    21. console.log('保存user', user.id)
    22. }
    23. getById(id: number): User {
    24. return this.data.find(item => item.id === id)
    25. }
    26. }
    27. const userCRUD = new UserCRUD()
    28. userCRUD.add(new User('tom', 12))
    29. userCRUD.add(new User('tom2', 13))
    30. console.log(userCRUD.data)

    泛型类

    泛型类看上去与泛型接口差不多。 泛型类使用( <>)括起泛型类型,跟在类名后面。

    1. class GenericNumber<T> {
    2. zeroValue: T;
    3. add: (x: T, y: T) => T;
    4. }
    5. let myGenericNumber = new GenericNumber<number>();
    6. myGenericNumber.zeroValue = 0;
    7. myGenericNumber.add = function(x, y) { return x + y; };

    GenericNumber类的使用是十分直观的,并且你可能已经注意到了,没有什么去限制它只能使用number类型。 也可以使用字符串或其它更复杂的类型。

    1. let stringNumeric = new GenericNumber<string>();
    2. stringNumeric.zeroValue = "";
    3. stringNumeric.add = function(x, y) { return x + y; };
    4. console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));

    与接口一样,直接把泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型。

    泛型约束

    如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性

    1. // 没有泛型约束
    2. function fn <T>(x: T): void {
    3. console.log(x.length) // 报错,因为目前不知道x是什么类型
    4. }

    我们可以使用泛型约束来实现

    1. interface Lengthwise {
    2. length: number;
    3. }
    4. // 指定泛型约束
    5. function fn2 <T extends Lengthwise>(x: T): void {
    6. console.log(x.length)
    7. }

    我们需要传入符合约束类型的值,必须包含必须 length 属性:

    1. fn2('abc')
    2. // fn2(123) // error number没有length属性
  • 相关阅读:
    机器学习硬件十年:性能变迁与趋势
    FEELM利用能源管理系统建设绿色工厂,减少500吨碳排放
    每日一题 2731. 移动机器人(中等,模拟)
    顺序表<数据结构 C 版>
    AJAX学习(四)
    如何创建springboot项目
    unity自制循环匀速动画
    Cadence Allegro PCB设计88问解析(十七) 之 Allegro中焊盘的全连接和花焊盘
    基于Yolov8的野外烟雾检测(3):动态蛇形卷积(Dynamic Snake Convolution),实现暴力涨点 | ICCV2023
    8、在一个数组中找出和为n的两个数
  • 原文地址:https://blog.csdn.net/weixin_43880991/article/details/125416325