TypeScript 泛型约束
摘要:在本教程中,你将了解 TypeScript 中的泛型约束。
TypeScript 中泛型约束简介
考虑以下示例:
function merge<U, V>(obj1: U, obj2: V) {
return {
...obj1,
...obj2
};
}
merge()
是合并两个对象的通用函数。 例如:
let person = merge(
{ name: 'John' },
{ age: 25 }
);
console.log(result);
输出:
{ name: 'John', age: 25 }
它工作得很好。
merge()
函数需要两个对象。 但是,它并不会阻止传递像这样的非对象参数:
let person = merge(
{ name: 'John' },
25
);
console.log(person);
输出:
{ name: 'John' }
TypeScript 不会发出任何错误。
你也许希望向 merge()
函数添加约束,以便它仅适用于对象,而不是处理所有的类型。
为此,你需要列出作为 U
和 V
类型约束的要求。
为了表示约束,你可以使用 extends
关键字。 例如:
function merge<U extends object, V extends object>(obj1: U, obj2: V) {
return {
...obj1,
...obj2
};
}
由于 merge()
函数现在受到限制,因此它将不再适用于所有类型。 相反,它仅接收对象类型的参数。
以下将导致错误:
let person = merge(
{ name: 'John' },
25
);
报错:
Argument of type '25' is not assignable to parameter of type 'object'.
在泛型约束中使用类型参数
TypeScript 允许你声明一个受另一个类型参数约束的类型参数。
下面的 prop()
函数接受一个对象和一个属性名称。 它返回该属性的值。
function prop<T, K>(obj: T, key: K) {
return obj[key];
}
编译器发出以下错误:
Type 'K' cannot be used to index type 'T'.
要修复此报错,需要向 K
添加约束以确保它是 T
的键,如下所示:
function prop<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
如果将 obj
上存在的属性名传递给 prop
函数,编译器不会报错。 例如:
let str = prop({ name: 'John' }, 'name');
console.log(str);
输出:
John
但是,如果你传递第一个参数中不存在的键,编译器将发出错误:
let str = prop({ name: 'John' }, 'age');
报错:
Argument of type '"age"' is not assignable to parameter of type '"name"'.
概括
- 使用
extends
关键字将类型参数限制为特定类型。 - 使用
extends keyof
来约束属于另一个对象的属性的类型。