# 泛型约束
在本教程中,你将学习 TypeScript 中的泛型约束。
# TypeScript 中的泛型约束介绍
思考以下例子:
function merge<U, V>(obj1: U, obj2: V) {
return {
...obj1,
...obj2,
};
}
1
2
3
4
5
6
2
3
4
5
6
merge()
是一个可以合并两个对象的泛型函数:
let person = merge({ name: 'John' }, { age: 25 });
console.log(result);
1
2
3
2
3
输出:
{ name: 'John', age: 25 }
1
它工作地很好。merge()
函数接受两个对象,但它无法阻止你传递一个非对象的参数,如下所示:
let person = merge({ name: 'John' }, 25);
console.log(person);
1
2
3
2
3
输出:
{
name: 'John';
}
1
2
3
2
3
TypeScript 没有发出任何的错误提示。你可能想给 merge()
函数添加一个约束,使得它只能处理对象而不处理其他的类型的参数。要做到这一点,你需要提出要求,作为 U
和 V
类型的约束。
为了表示约束,你可以使用 extends
关键字:
function merge<U extends object, V extends object>(obj1: U, obj2: V) {
return {
...obj1,
...obj2,
};
}
1
2
3
4
5
6
2
3
4
5
6
因为 merge()
函数的参数受到了约束,它将不再适合用于所有类型的参数调用,它现在只适合用于 object
类型的参数调用。
下面将抛出一个错误提示:
let person = merge({ name: 'John' }, 25);
1
错误提示:
Argument of type '25' is not assignable to parameter of type 'object'.
1
# 在泛型约束中使用行参
TypeScript 允许声明受另外一个类型参数约束的类型参数。
下面的 prop()
函数接受一个对象和一个属性名,它会返回属性的值:
function prop<T, K>(obj: T, key: K) {
return obj[key];
}
1
2
3
2
3
编译器会抛出下面的错误提示:
Type 'K' cannot be used to index type 'T'.
1
为了修复这个错误,你在 K
上添加一个约束来确保它是 T
类型的键,如下所示:
function prop<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
1
2
3
2
3
如果你传递给 prop()
函数一个 obj
对象上存在的属性明,编译器不会抛出错误提示,如下所示:
let str = prop({ name: 'John' }, 'name');
console.log(str);
1
2
2
输出:
John
1
然而如果传递一个在第一个参数上不存在的属性名,编译器会抛出一个错误提示:
let str = prop({ name: 'John' }, 'age');
1
错误提示:
Argument of type '"age"' is not assignable to parameter of type '"name"'.
1
# 小结
- 使用
extends
关键字将类型参数约束为指定类型; - 使用
extends keyof
约束类型为另外一个对象的属性集合。