T extends U 泛型约束
最后更新:2026-10-22
T extends U 泛型约束
约束(extends)给类型参数"划定范围":<T extends HasId> 承诺"T 至少有 id: number"。约束之内可以放心访问 T 的公共成员,约束之外(传个 string 进来)编译期直接拒绝——比 any 安全,比具体类型灵活。
| 分组 | 泛型 |
|---|---|
| 类型 | 语法 |
| 严格模式 | 不需要 |
ℹ️ 说明 编辑器将 TypeScript 转译为 JavaScript 后运行(不做类型检查);类型检查结果见示例 Output。
📝 语法
interface HasId {
id: number;
}
function findById<T extends HasId>(items: T[], id: number): T | undefined {
return items.find((item) => item.id === id);
}
⚙️ 参数
| T extends HasId | 约束:实参类型必须兼容 HasId(至少含 id: number) |
|---|---|
| T | undefined | 返回类型保留实参的精确形状:传入什么形状的数组,就取回同样形状的元素 |
返回值:与未加约束的泛型一致——保留实参的精确类型;区别在于函数体内 T 的可用成员变多了。
▶ 示例
修改下面的代码,点击试一试查看转译运行结果:
输出:
Desk
未找到
(转译后运行输出;products 的元素有额外字段没关系——结构化类型只检查约束要求的成员)
💡 要点
ℹ️ 说明 约束不要求"恰好等于":{ id: 1, name: "Lamp", price: 59 } 的额外字段不影响兼容——结构化类型只检查约束要求的成员是否齐备。
💡 提示 内联约束省掉中间接口:function sumLengths<T extends { length: number }>(a: T, b: T) 直接描述"只要有 length";复杂约束才值得提接口。
⚠️ 注意 约束给的是"下限":T extends HasId 只保证 id 存在,item.name 在编译器眼里仍不存在——除非再约束 name: string。
🏷️ 相关泛型
💡 相关案例
更多案例即将上线。
📚 相关教程
❓ 常见问题
Q 约束和泛型默认值能同时用吗?
A 能且常配合:<T extends HasId = User>——不传时用默认 User,传了必须满足 HasId。默认值必须在约束范围内。
Q 怎么约束"必须是某几个字面量之一"?
A 用字面量联合:function set<K extends "light" | "dark">(theme: K)。K 会收窄到具体字面量,越界值编译报错。
Q 多个类型参数互相约束怎么写?
A 让后者引用前者:<K extends keyof T>——K 的取值范围由 T 决定,这是 keyof 模式的核心,保证键名与对象真实匹配。