首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
开篇:用正确的方式学习 TypeScript
打造 TypeScript 的开发环境
TypeScript中的原始类型与对象类型
TypeScript中的字面量类型与枚举
TypeScript中的函数重载与面向对象
TypeScript的内置类型:any、unknown、never 与类型断言
TypeScript 类型工具
TypeScript 中无处不在的泛型
TypeScript 类型系统层级:从 Top Type 到 Bottom Type
TypeScript 类型里的逻辑运算:条件类型与 infer
TypeScript 中的内置工具类型基础
TypeScript 反方向类型推导:用好上下文相关类型
TypeScript 函数类型:协变与逆变的比较
TypeScript中类型编程与类型体操的意义
TypeScript模板字符串类型
TypeScript模板字符串工具类型进阶
TypeScript类型声明、类型指令与命名空间
在 React 中愉快地使用 TypeScript:内置类型与泛型坑位
让 ESLint 来约束你的 TypeScript 代码:配置与规则集介绍
TypeScript装饰器与反射元数据
TypeScript控制反转与依赖注入
TSConfig 全解(上):构建相关配置
TSConfig 全解(下):检查相关、工程相关配置
当前位置:
首页>>
技术小册>>
TypeScript入门指南
小册名称:TypeScript入门指南
泛型是 TypeScript 中的重要特性,它可以让我们在编写代码时更加灵活、安全和可复用。 泛型的概念很简单:就是定义一种通用的类型或函数,可以用来适应不同类型的数据。在实际编程中,泛型的应用非常广泛,包括函数、类、接口等方面。本文将通过具体的代码示例,介绍 TypeScript 中泛型的基本概念、应用场景以及注意事项,希望可以帮助读者更好地理解和使用泛型。 ---------------------------------- **1、泛型基础** 泛型可以理解为一种类型占位符,它可以用来表示任何类型。在 TypeScript 中,我们可以使用尖括号(<>)来定义泛型,例如: ```javascript function identity<T>(arg: T): T { return arg; } ``` 在这个例子中,identity 函数使用了泛型 T,它代表任意类型。函数的参数和返回值都是类型为 T 的值。通过这种方式,我们可以在函数中使用任何类型的值,而不需要对每种类型都编写一份代码。 当我们调用 identity 函数时,需要指定泛型的具体类型。例如: ```javascript let output1 = identity<string>("hello"); // output1 的类型为 string let output2 = identity<number>(1); // output2 的类型为 number ``` 我们也可以不指定泛型的类型,让 TypeScript 根据参数的类型自动推导出泛型的类型: ```javascript let output3 = identity("hello"); // output3 的类型为 string let output4 = identity(1); // output4 的类型为 number ``` 以上代码中,TypeScript 根据参数的类型自动推导出了泛型 T 的类型。 **2、泛型函数的应用** 泛型函数可以用于解决不同类型的数据处理问题。例如,我们可以编写一个函数,用来返回一个数组的第一个元素: ```javascript function getFirstElement<T>(arr: T[]): T | undefined { return arr[0]; } ``` 在这个例子中,getFirstElement 函数使用了泛型 T,它代表数组元素的类型。函数的参数是一个类型为 T 的数组,函数的返回值类型是 T 或 undefined。通过这种方式,我们可以用这个函数来获取任意类型的数组的第一个元素: ```javascript let arr1 = [1, 2, 3]; let firstElement1 = getFirstElement<number>(arr1); // firstElement1 的类型为 number let arr2 = ["a", "b", "c"]; let firstElement2 = getFirstElement<string>(arr2); // firstElement2 的类型为 string ``` 以上代码中,我们分别传入了一个 number 类型的数组和一个 string 类型的数组,调用了 getFirstElement 函数,并通过泛型指定了数组元素的类型。函数的返回值类型根据泛型的类型自动推导出来。 **3、泛型类的应用** 泛型不仅可以应用于函数中,还可以应用于类和接口中。下面我们来看一个泛型类的例子: ```javascript class Pair<T, U> { constructor(public first: T, public second: U) {} swap(): Pair<U, T> { return new Pair(this.second, this.first); } } ``` 在这个例子中,我们定义了一个 Pair 类,它使用了两个泛型类型 T 和 U,代表两个不同的类型。类的构造函数需要两个参数,一个类型为 T,一个类型为 U,并将它们分别保存在 first 和 second 属性中。Pair 类还定义了一个 swap 方法,用于将 first 和 second 属性交换位置,并返回一个新的 Pair 对象。 我们可以使用 Pair 类来创建不同类型的对象: ```javascript let pair1 = new Pair<string, number>("hello", 123); // pair1 的类型为 Pair<string, number> let pair2 = new Pair<number, boolean>(123, true); // pair2 的类型为 Pair<number, boolean> let swappedPair1 = pair1.swap(); // swappedPair1 的类型为 Pair<number, string> let swappedPair2 = pair2.swap(); // swappedPair2 的类型为 Pair<boolean, number> ``` 以上代码中,我们分别创建了两个 Pair 对象,一个使用了 string 和 number 类型,一个使用了 number 和 boolean 类型。我们还调用了 swap 方法,并通过泛型指定了交换后新对象的类型。 **4、泛型约束** 在使用泛型时,有时我们需要对泛型进行一些约束,以确保它符合某些要求。例如,我们需要对泛型进行一些操作,但这些操作只能应用于特定类型。在这种情况下,我们可以使用泛型约束。 下面是一个例子,它演示了如何使用泛型约束: ```javascript interface Lengthwise { length: number; } function logLength<T extends Lengthwise>(arg: T): void { console.log(arg.length); } ``` 在这个例子中,我们定义了一个接口 Lengthwise,它包含了一个 length 属性,类型为 number。然后我们编写了一个函数 logLength,它使用了泛型 T,并对泛型进行了约束,要求它必须是一个实现了 Lengthwise 接口的类型。 通过这种方式,我们可以保证 logLength 函数只会接收实现了 Lengthwise 接口的类型。我们可以传入一个字符串或数组等类型的数据,因为它们都实现了 length 属性: ```javascript logLength("hello"); // 输出 5 logLength([1, 2, 3]); // 输出 3 但如果我们传入一个不实现 `Lengthwise` 接口的类型,比如一个数字,则会产生编译错误: ```typescript logLength(123); // 编译错误:数字类型没有 length 属性 ``` 另一个例子是使用泛型约束实现工厂模式。我们可以定义一个工厂接口 Factory<T>,它包含一个方法 create,用于创建类型为 T 的对象。然后我们编写一个泛型函数 createObject,使用泛型约束 T extends Factory<T>,表示泛型 T 必须实现 Factory<T> 接口。函数内部调用 create 方法创建一个对象。 以下是代码示例: ```javascript interface Factory<T> { create(): T; } function createObject<T extends Factory<T>>(factory: T): T { return factory.create(); } ``` 我们可以定义一个 PersonFactory 类,实现了 Factory<Person> 接口,并重写了 create 方法,用于创建一个 Person 对象: ```javascript class Person { constructor(public name: string, public age: number) {} } class PersonFactory implements Factory<Person> { create(): Person { return new Person("Tom", 18); } } ``` 然后我们可以调用 createObject 函数,传入一个 PersonFactory 对象,创建一个 Person 对象: ```javascript let person = createObject(new PersonFactory()); // person 的类型为 Person console.log(person.name); // 输出 "Tom" console.log(person.age); // 输出 18 ``` 以上例子中,我们使用了泛型约束 T extends Factory<T>,要求泛型 T 必须实现 Factory<T> 接口。然后我们定义了一个 PersonFactory 类,实现了 Factory<Person> 接口,并重写了 create 方法,用于创建一个 Person 对象。最后我们调用 createObject 函数,传入一个 PersonFactory 对象,创建了一个 Person 对象。 **小结** TypeScript 中的泛型为我们提供了一种通用的方法,可以在编写代码时,不必提前指定具体的类型,而是将类型作为参数进行传递。泛型可以应用于函数、类、接口等不同的场景,使我们的代码更加灵活和通用。在使用泛型时,我们可以通过泛型约束来限制泛型的类型范围,以确保泛型符合某些要求。
上一篇:
TypeScript 类型工具
下一篇:
TypeScript 类型系统层级:从 Top Type 到 Bottom Type
该分类下的相关小册推荐:
TypeScript开发实战
剑指TypeScript
TypeScript 全面进阶指南