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() 函数的参数受到了约束,它将不再适合用于所有类型的参数调用,它现在只适合用于 object 类型的参数调用。

下面将抛出一个错误提示:

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];
}

如果你传递给 prop() 函数一个 obj 对象上存在的属性明,编译器不会抛出错误提示,如下所示:

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"'.

小结

教程来源于Github,感谢cody1991大佬的无私奉献,致敬!

技术教程推荐

硅谷产品实战36讲 -〔曲晓音〕

算法面试通关40讲 -〔覃超〕

面试现场 -〔白海飞〕

深入拆解Tomcat & Jetty -〔李号双〕

张汉东的Rust实战课 -〔张汉东〕

陶辉的网络协议集训班02期 -〔陶辉〕

容量保障核心技术与实战 -〔吴骏龙〕

如何落地业务建模 -〔徐昊〕

朱涛 · Kotlin编程第一课 -〔朱涛〕