TypeScript 泛型约束怎么写

很多前端小伙伴刚用 TypeScript 时,常会遇到“写的函数明明能处理多种数据,却被 TS 报类型错误”的情况——比如写一个获取对象属性的工具函数,想兼容字符串、数字等类型的 key,结果 TS 总提示“类型不匹配”。这其实就是没用好泛型约束,它能帮 TS 精准把控函数的输入输出,既灵活又规范。

先搞懂:泛型约束到底是啥?

简单说,泛型是给代码留的“类型占位符”,而泛型约束就是给这个占位符“加规矩”——告诉 TS“这个泛型变量必须满足某个条件,不能随便传值”。

TypeScript 泛型约束怎么写

举个生活化的例子:你开了家奶茶店,不管客人点什么,都要给杯子贴“订单标签”——标签上必须有“订单号”这一项,不能是空白的。这里“标签必须有订单号”就是约束,而用 TS 的话,就是给泛型变量加上这个规则。

最常用的写法:用 extends 加基础约束

TS 里给泛型加约束,核心用 extends 关键字。最基础的场景是“要求泛型是某个类型的子类型”,最常见的就是约束为对象类型——毕竟我们写函数时,很多时候是处理对象的属性。

比如刚才说的获取对象属性的函数:如果直接写 function getProp<T>(obj: T, key: string),TS 会报错,因为没法确定 key 真的是 obj 上有的属性。这时候就可以用泛型约束,让 TS 知道 key 必须是 obj 的键:

`typescript

// 用 keyof 取出对象的所有键,约束泛型 K 只能是这些键

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

return obj[key];

}

// 用的时候就不会错了

const user = { name: "小明", age: 18 };

const userName = getProp(user, "name"); // 正确,返回 string

// getProp(user, "gender"); // TS 直接报错:不存在这个键

`

这个例子里,T extends object 是约束第一个参数必须是对象,K extends keyof T 是约束第二个参数必须是对象的合法键,既保留了函数的灵活性,又避免了传错 key 的低级错误。

进阶场景:约束泛型的具体属性

有时候你需要更细的约束,比如要求泛型必须有某个固定属性,不管其他属性是什么。还是用奶茶店的例子:要求所有“饮品订单”的标签必须有 drinkType 属性,不能是没有这个属性的其他订单。

写法也很简单,直接在 extends 里写需要的属性结构:

`typescript

// 约束泛型 T 必须有 drinkType 属性,类型是 string

type DrinkOrder = { drinkType: string; [key: string]: any };

function makeDrink<T extends DrinkOrder>(order: T): string {

return 制作${order.drinkType},配料:${order.toppings || "默认珍珠"};

}

// 正确的订单可以传

const milkTea = { drinkType: "珍珠奶茶", toppings: "波霸" };

makeDrink(milkTea); // 正常运行

// 缺少 drinkType 的订单会报错

// makeDrink({ dessert: "蛋糕" }); // TS 报错

`

这里 DrinkOrder 就是一个“带约束的类型模板”,用 extends 把泛型限制成符合这个模板的类型,不管你加其他属性,只要有 drinkType 就行。

避坑提醒:别把泛型约束写太死

很多新手会犯一个错:把约束写得太具体,反而失去了泛型的灵活性。比如刚才的 getProp 函数,要是写成 K extends string,那 TS 就没法判断 key 是不是对象的合法属性了,等于白加约束。

再举个反面例子:

`typescript

// 错误写法:把 K 约束成 string,虽然能运行,但失去了类型检查

function badGetProp<T, K extends string>(obj: T, key: K) {

return obj[key as keyof T];

}

badGetProp(user, "gender"); // 虽然 TS 不报错,但运行时会 undefined

`

所以记住:泛型约束要“刚好够”——既解决类型问题,又不限制必要的灵活性。

简单来说,TypeScript 泛型约束就是给你的代码“戴个安全套”,既能放开手脚写灵活的逻辑,又能挡住各种非法输入的坑,是 TS 写大型项目时必不可少的小工具。

上一篇 JavaScript 如何做请求封装