- • extends 用于约束泛型类型
- • keyof 获取类型的所有键
- • & 实现多重约束
- • 约束让泛型更安全、更具体
6.5 泛型约束
限制泛型类型的范围
🎯 学习目标
- 理解泛型约束的概念和作用
- 掌握 extends 约束语法
- 学会使用 keyof 进行约束
- 了解多重约束
📝 基本约束
// 约束 T 必须有某些属性
interface HasId {
id: number;
}
function findById<T extends HasId>(items: T[], id: number): T | undefined {
return items.find(item => item.id === id);
}
interface User extends HasId {
name: string;
}
const users: User[] = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
];
const user = findById(users, 1); // { id: 1, name: 'Alice' }
// 没有 id 的数组会报错
const numbers = [1, 2, 3];
// findById(numbers, 1); // Error: number 不满足 HasId
🔧 keyof 约束
// 获取对象属性值的函数
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
const person = {
name: 'Alice',
age: 30,
city: 'Beijing'
};
const name = getProperty(person, 'name'); // string
const age = getProperty(person, 'age'); // number
// getProperty(person, 'email'); // Error: 'email' 不是 person 的属性
// 设置对象属性值的函数
function setProperty<T, K extends keyof T>(obj: T, key: K, value: T[K]): void {
obj[key] = value;
}
setProperty(person, 'name', 'Bob');
setProperty(person, 'age', 31);
🔀 多重约束
interface HasId {
id: number;
}
interface HasName {
name: string;
}
// 多重约束:T 必须同时满足两个接口
function printEntity<T extends HasId & HasName>(entity: T): void {
console.log(`ID: ${entity.id}, Name: ${entity.name}`);
}
interface User extends HasId, HasName {
email: string;
}
const user: User = { id: 1, name: 'Alice', email: 'alice@example.com' };
printEntity(user);
// 使用类型参数约束另一个类型参数
function createObject<K extends string, V>(key: K, value: V): Record<K, V> {
return { [key]: value } as Record<K, V>;
}
const obj = createObject('name', 'Alice'); // { name: string }
📝 本节小结
✅