跳到主要内容

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() 函数添加约束,以便它仅适用于对象,而不是处理所有的类型。

为此,你需要列出作为 UV 类型约束的要求。

为了表示约束,你可以使用 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 来约束属于另一个对象的属性的类型。