TypeScript系列:第三篇 - 泛型

上一篇 《TypeScript系列:续篇 - 对象类型(含数组、元数组、函数)》 中有提及对象类型中的"泛型"使用,本篇将详细展开...

TypeScript 引入泛型是为了增强代码的复用性、健壮性。

ts 复制代码
interface Box {
  contents: any;
}

interface Box<Type> {
  contents: Type;
}

泛型允许开发者编写一次代码,适用于多种数据类型,减少冗余。

其在编译时提供类型检查,提前发现错误,提高代码的健壮性。

定义

泛型(Generics)本质上是一种参数化类型。

在定义时不指定具体数据类型 ,用一个或多个占位符(通常用字母「如 TUV」)来表示类型参数;而在使用时指定具体的数据类型

ts 复制代码
function identity<T>(arg: T): T {
  return arg;
}

上述函数返回值的类型参数类型相关;可以接收任何类型的参数,并返回相同类型的值。

<T> 指类型参数,可以将其理解为类型声明需要的变量,在调用时传入具体的参数类型。

  • 调用时提供具体类型
ts 复制代码
identity<string>('ligang')
  • 省略不写,TypeScript 通常可以在泛型调用中推断出预期的类型参数。
ts 复制代码
identity('ligang') 

泛型写法

泛型可以在:函数、接口、类和别名 中定义。

泛型函数

定义一个泛型函数identity,它接受一个类型参数 T,并返回这个类型的值

ts 复制代码
function identity<T>(arg: T): T {
    return arg;
}

let output = identity<string>("ligang"); // 当然,这里的string可省略,Typescript会自行推断

泛型接口

定义了一个泛型接口 Lengthwise<T>,具有 length 属性和 value 属性,其中 length 是一个数字,而 value 是一个类型为T的值。

泛型函数 classArray ,接受一个类型为 Lengthwise<T> 的参数,并返回一个类型为 Lengthwise<T> 的值。

ts 复制代码
interface Lengthwise<T> {
  length: number;
  value: T;
}

function classArray<T>(arg: Lengthwise<T>): Lengthwise<T> {
  return arg;
}

classArray({ value: 'TypeScript', length: 10 });

泛型类

定义泛型类 Box<T> ,其构造函数接受一个类型参数 T 和一个参数 content,并将这个 content 赋值给类的私有属性 _content

ts 复制代码
class Box<T> {
  private _content: T;

  constructor(content: T) {
      this._content = content;
  }

  get content(): T {
      return this._content;
  }
}

const box = new Box<number>(123);

🐾 泛型别名

传入一个类型,得到这个类型与 undefinednull 的一个联合类型。

ts 复制代码
type Nullable<T> = T | undefined | null;

let a: Nullable<string> = 'ligang';
let b: Nullable<string> = null;
let c: Nullable<string>;
经典案例

泛型与别名的结合实现表格响应体的类型:

1️⃣ 响应结构体

ts 复制代码
interface Res<T> {
  status: 'success' | 'error';	// 状态码
  data: T;											// 返回数据
}

2️⃣ table 数据格式

ts 复制代码
interface TableData<T> {
  pageNumber: number;	// 页码
  pageSize: number;		// 每页条数
  total: number;			// 总条数
  data: T[];					// 表格数据
}

3️⃣ 结合:响应表格结构体

ts 复制代码
type ResTableData<T> = Res<TableData<T>>;
  • 这里的T 为表格数据类型

4️⃣ 调用示例

ts 复制代码
// 表格数据为 string
const tableData: ResTableData<string> = {
  status: 'success',
  data: {
    pageNumber: 1,
    pageSize: 10,
    total: 100,
    data: ['1', '2'],
  },
};

// 表格数据为 city
interface city {
  code: number;
  name: string;
}
const res: ResTableData<city> = {
  status: 'success',
  data: {
    pageNumber: 1,
    pageSize: 10,
    total: 100,
    data: [
      { code: 10010, name: '北京' },
      { code: 10011, name: '上海' },
    ],
  },
};

常见的泛型表示

类型 说明 示例
Array<T> T 可指定任何类型 let myAry: Array<number> = [1, 2, 3]
Map<K, V> KV 分别是键和值的类型参数,可指定任何类型 let myMap: Map<string, number> = new Map()
Set<T> T 可指定任何类型 let mySet: Set<number> = new Set([1, 2, 3])
Promise<T> T 可指定任何类型 let tableData = (): Promise<ResTableData<city>> => fetch('...').then((res) => res.json())
ts 复制代码
interface Array<Type> {
  length: number;
  pop(): Type | undefined;
  push(...items: Type[]): number;
  ...
}

泛型约束

如果需要限制泛型的使用范围,可以使用泛型约束!

ts 复制代码
<Type extends Constraint>

🌿 示例:提供一个获取对象属性的方法

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

getProp({ name: 'ligang', age: '34' }, 'name'); 	 // 正确
getProp({ name: 'ligang', age: '34' }, 'address'); // 错误,address 对象中不存在

具体报错:类型""address""的参数不能赋给类型""name" | "age""的参数

keyof

keyof 是 TypeScript 中的关键字,用于从一个对象类型中提取所有键(属性名)的联合类型。

ts 复制代码
interface Person {
  name: string;
  age: number;
}
type PersonKeys = keyof Person; // 'name' | 'age'

✊ 综上,解释 getProp() ,只能获取对象既存的属性


除了使用 keyof 方式,也可以自定义约束条件~~

🍃 示例:限制必须有 length 属性

函数的作用:比较两个实现了 Len 接口的值的长度,并返回长度较大的那个值。

ts 复制代码
interface Len {
  length: number;
}
function compareLen<T extends Len, U extends Len>(a: T, b: U) {
  return a.length - b.length ? a : b;
}

compareLen([1, 2, 3], 'ab');

总结

泛型不仅提高了代码的可重用性和灵活性,同时也保证了类型的安全性。掌握好泛型的使用对于提升 TypeScript 编程技能至关重要!

相关推荐
如果'\'真能转义说8 小时前
TypeScript - 利用GPT辅助学习
gpt·学习·typescript
樊南3 天前
【esp32&小程序】小程序篇02——连接git
javascript·git·小程序·typescript·gitee
记得开心一点嘛3 天前
uniapp --- 配置文件
前端·typescript·uni-app
源之缘-OFD先行者3 天前
TypeScript 使用 VSCode 简介
javascript·vscode·typescript
明月看潮生4 天前
青少年编程与数学 02-006 前端开发框架VUE 27课题、TypeScript
vue.js·青少年编程·typescript·编程与数学
觉醒法师4 天前
HarmonyOS开发中模拟器TextInput表单类的无法输入中文字符问题
前端·javascript·华为·typescript·harmonyos
m0_512744645 天前
TypeScript 与后端开发Node.js
javascript·typescript·node.js
qq_530245195 天前
自定义提示确认弹窗-vue
前端·vue.js·typescript
风茫5 天前
掌握 TypeScript 的 `Omit` 工具类型:灵活操作对象属性的艺术
javascript·ubuntu·typescript
汪子熙5 天前
理解 TypeScript 条件类型与类型推断
前端·javascript·typescript