ts的范性

范性 在使用的时候才确定 类型

🧩 一、泛型是什么?

👉 泛型是 类型的参数化(Type as parameter)

它允许我们在定义函数、接口或类时,不预先指定具体的类型,而是在使用时再传入类型。

例子:没有泛型的函数

sql 复制代码
function identity(value: any): any {
  return value;
}

问题是:

  • 你传入 number,返回值类型却成了 any;
  • TypeScript 无法推断返回值类型,类型安全丢失。

✅ 使用泛型改写

r 复制代码
function identity<T>(value: T): T {
  return value;
}
  • T 是一个类型变量(type variable);
  • 当你调用时,TS 会根据传入值自动推断类型
scss 复制代码
identity(123);      // 推断 T 为 number
identity("hello");  // 推断 T 为 string

返回值类型与参数类型保持一致,类型安全、灵活。


🧠 二、泛型的语法结构

基本结构是:

r 复制代码
function fn<T>(arg: T): T {
  return arg;
}
  • <T>:定义一个泛型变量;
  • T 可以是任意名字,比如 <Type>, <U>, <K, V>
  • T 在函数内部当作一种占位符使用。

🚀 三、泛型函数、接口、类型别名、类

1️⃣ 泛型函数

scss 复制代码
function firstElement<T>(arr: T[]): T {
  return arr[0];
}

firstElement([1, 2, 3]);     // T 推断为 number
firstElement(["a", "b"]);    // T 推断为 string

2️⃣ 泛型接口

csharp 复制代码
interface Box<T> {
  value: T;
}

const stringBox: Box<string> = { value: "hello" };
const numberBox: Box<number> = { value: 123 };

3️⃣ 泛型类型别名

typescript 复制代码
type Pair<T, U> = [T, U];
const p1: Pair<string, number> = ["age", 18];

4️⃣ 泛型类

kotlin 复制代码
class DataStore<T> {
  private data: T[] = [];

  add(item: T) {
    this.data.push(item);
  }

  getAll(): T[] {
    return this.data;
  }
}

const stringStore = new DataStore<string>();
stringStore.add("hello");
stringStore.add("world");

🧮 四、泛型约束(Constraints)

有时你不希望 T 是任意类型,而是必须"具备某些特性"。

例子:想访问 .length 属性

r 复制代码
function getLength<T>(arg: T): number {
  return arg.length; // ❌ 报错:T 可能没有 length
}

解决办法:

scss 复制代码
interface HasLength {
  length: number;
}

function getLength<T extends HasLength>(arg: T): number {
  return arg.length;
}

getLength("hello");  // ✅ string 有 length
getLength([1, 2, 3]); // ✅ 数组有 length
getLength(123);       // ❌ number 没有 length

T extends U 表示:

泛型 T 必须是类型 U 的子类型(或满足其结构)。


🧩 五、泛型默认值

如果你想给泛型一个默认类型:

ini 复制代码
interface ApiResponse<T = any> {
  code: number;
  data: T;
}

const res: ApiResponse = { code: 200, data: "ok" }; // 默认 T 为 any

🧩 六、泛型约束之间的依赖(类型参数之间的关系)

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

const person = { name: "Alice", age: 18 };

getProperty(person, "name"); // ✅ OK
getProperty(person, "gender"); // ❌ Error:key 不存在于 T 中

解释:

  • K extends keyof T 表示 K 必须是 T 的键名之一;
  • 这是 泛型之间的依赖约束,非常常见于框架源码。

🧩 七、泛型工具与推断技巧

1️⃣ 显式指定类型

c 复制代码
identity<string>("hi");

2️⃣ 类型推断

TS 一般能自动推断类型,无需显式指定。


3️⃣ 泛型工具类型(TS 内置)

TypeScript 提供了许多内置泛型工具类型:

工具类型 作用
Partial<T> 将所有属性变为可选
Required<T> 将所有属性设为必需
Readonly<T> 将所有属性设为只读
Pick<T, K> 从类型 T 中挑出若干属性
Record<K, T> 构造一个键为 K、值为 T 的对象类型
ReturnType<T> 提取函数的返回值类型

这些都是通过泛型 + 映射类型 + 条件类型实现的。


⚙️ 八、真实案例:Axios 泛型返回值

ini 复制代码
axios.get<User[]>('/api/users')
  .then(res => {
    res.data.forEach(u => console.log(u.name));
  });

这里的 axios.get<T> 使用了泛型:

  • 告诉 TS 响应体数据的类型;
  • res.data 自动推断为 User[]
相关推荐
0思必得013 小时前
[Web自动化] Selenium处理动态网页
前端·爬虫·python·selenium·自动化
东东51613 小时前
智能社区管理系统的设计与实现ssm+vue
前端·javascript·vue.js·毕业设计·毕设
catino13 小时前
图片、文件的预览
前端·javascript
layman052815 小时前
webpack5 css-loader:从基础到原理
前端·css·webpack
半桔15 小时前
【前端小站】CSS 样式美学:从基础语法到界面精筑的实战宝典
前端·css·html
AI老李15 小时前
PostCSS完全指南:功能/配置/插件/SourceMap/AST/插件开发/自定义语法
前端·javascript·postcss
_OP_CHEN15 小时前
【前端开发之CSS】(一)初识 CSS:网页化妆术的终极指南,新手也能轻松拿捏页面美化!
前端·css·html·网页开发·样式表·界面美化
啊哈一半醒15 小时前
CSS 主流布局
前端·css·css布局·标准流 浮动 定位·flex grid 响应式布局
PHP武器库15 小时前
ULUI:不止于按钮和菜单,一个专注于“业务组件”的纯 CSS 框架
前端·css
电商API_1800790524715 小时前
第三方淘宝商品详情 API 全维度调用指南:从技术对接到生产落地
java·大数据·前端·数据库·人工智能·网络爬虫