TypeScript 类、泛型的使用实践记录 | 豆包MarsCode AI刷题

111 阅读4分钟

TypeScript类与泛型:从入门到实践

引言

作为一名TypeScript初学者,我在学习过程中发现类和泛型是两个既重要又容易混淆的概念。本文将从基础开始,记录我学习TypeScript类和泛型的心得体会,希望能帮助其他初学者更好地理解这些概念。

1. 类的基础使用

首先,让我们从最基本的类开始:

// 一个简单的用户类
class User {
  // 类的属性
  name: string;
  age: number;

  // 构造函数
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }

  // 类的方法
  sayHello() {
    console.log(`你好,我是${this.name},今年${this.age}岁`);
  }
}

// 使用这个类
const user = new User('小明', 18);
user.sayHello(); // 输出:你好,我是小明,今年18岁

在学习过程中,我发现使用类的几个要点:

  1. 需要先声明属性,再在构造函数中初始化
  2. 方法不需要function关键字
  3. 使用this来访问类的属性和方法

访问修饰符

接下来学习了访问修饰符,这是控制类成员访问权限的方式:

class Student {
  public name: string;        // 公开的,任何地方都能访问
  private score: number;      // 私有的,只能在类内部访问
  protected grade: string;    // 受保护的,只能在类内部和子类中访问

  constructor(name: string, score: number, grade: string) {
    this.name = name;
    this.score = score;
    this.grade = grade;
  }

  // 获取分数的方法
  getScore() {
    return this.score; // 可以访问私有属性
  }
}

2. 初识泛型

刚开始接触泛型时,我觉得很难理解。后来我把它想象成"类型占位符",就容易多了:

// 不使用泛型的数组
const numbers: number[] = [1, 2, 3];
const strings: string[] = ['a', 'b', 'c'];

// 使用泛型的数组
const numbers2: Array<number> = [1, 2, 3];
const strings2: Array<string> = ['a', 'b', 'c'];

一个简单的泛型函数

// 创建一个返回任何传入值的函数
function returnItem<T>(item: T): T {
  return item;
}

// 使用这个函数
const numberItem = returnItem<number>(42);    // 返回数字
const stringItem = returnItem<string>('hello');// 返回字符串
const booleanItem = returnItem(true);         // TypeScript会自动推断类型

这里的<T>就像一个占位符,告诉TypeScript:"这个类型稍后再定"。

3. 实际案例:创建一个简单的购物车

结合类和泛型,我创建了一个简单的购物车示例:

// 商品接口
interface Product {
  id: number;
  name: string;
  price: number;
}

// 购物车类
class ShoppingCart<T extends Product> {
  private items: T[] = [];

  // 添加商品
  addItem(item: T) {
    this.items.push(item);
  }

  // 移除商品
  removeItem(id: number) {
    this.items = this.items.filter(item => item.id !== id);
  }

  // 获取所有商品
  getItems(): T[] {
    return this.items;
  }

  // 计算总价
  getTotalPrice(): number {
    return this.items.reduce((total, item) => total + item.price, 0);
  }
}

// 使用购物车
const cart = new ShoppingCart<Product>();
cart.addItem({ id: 1, name: '苹果', price: 5 });
cart.addItem({ id: 2, name: '香蕉', price: 3 });

console.log(cart.getTotalPrice()); // 输出:8

4. 学习过程中的困惑与解决

困惑1:泛型约束

最初我不理解为什么需要泛型约束,后来通过这个例子明白了:

// 没有约束的泛型
function printProperty<T>(obj: T, key: string) {
  console.log(obj[key]); // 错误:obj可能没有key属性
}

// 使用约束的泛型
function printProperty<T extends { [key: string]: any }>(obj: T, key: string) {
  console.log(obj[key]); // 正确:已经确保obj有string类型的键
}

困惑2:类型推断

开始时我总是显式地指定泛型类型,后来学会了让TypeScript自己推断:

// 不需要显式指定类型
const numbers = returnItem(42);        // 自动推断为number
const strings = returnItem('hello');   // 自动推断为string

5. 实用小技巧

在学习过程中,我总结了一些有用的技巧:

  1. 使用接口定义类型
interface HasLength {
  length: number;
}

function logLength<T extends HasLength>(item: T) {
  console.log(item.length);
}

logLength('hello');     // 可以用于字符串
logLength([1, 2, 3]);  // 可以用于数组
  1. 默认类型参数
class Container<T = string> {
  value: T;
  
  constructor(value: T) {
    this.value = value;
  }
}

const stringContainer = new Container('hello'); // T 默认为 string
const numberContainer = new Container<number>(42); // 明确指定 T 为 number

总结

作为初学者,我的学习心得是:

  1. 循序渐进

    • 先掌握类的基础用法
    • 理解泛型的概念
    • 尝试结合使用类和泛型
  2. 多动手实践

    • 从简单的例子开始
    • 逐步增加复杂度
    • 解决实际问题
  3. 常见误区

    • 不要过度使用泛型
    • 记得添加适当的类型约束
    • 善用类型推断

建议:

  • 多看官方文档
  • 写代码时开启严格模式
  • 从简单的项目开始练习
  • 遇到问题多查看报错信息

TypeScript的学习是一个渐进的过程,不要期望一下子掌握所有概念。重要的是要多写代码,多实践!