介绍
TypeScript 是一种通用编程语言,广泛应用于各种开发环境。自发布以来,它获得了开发者和企业的广泛支持,GitHub 在 2022 年将其列为第四大最常用编程语言,便是最好的证明。此后,TypeScript 的地位日益提升。.
此外,TypeScript 的受欢迎程度也体现在其大量的就业机会上,LinkedIn 上发布了超过 20,000 个与 TypeScript 相关的职位,包括 Trivago 和 Stripe 在内的主要行业参与者选择将其技术栈迁移到 TypeScript。.
在本文中,我们将从头开始探索 TypeScript,以了解其优势,以及这些优势如何导致它在开发者社区中得到越来越广泛的应用。.
TypeScript 与 JavaScript
TypeScript并非全新概念。它是JavaScript的超集,旨在解决JavaScript自身的一些局限性。作为超集,TypeScript通过添加静态类型来扩展JavaScript。.
这种静态类型可以通过两种常见方式声明:
1.类型注解
这意味着在首次声明变量时就立即指定变量及其类型。例如:
let name: string = "Hygraph其中 name 是变量的名称,string 是变量的类型。.
2. 类型别名
这种方法涉及使用 type 关键字单独定义类型,然后使用该类型来注释变量。.
type StringType = {
name: string;
};
let name: StringType = { name: "Hygraph" };现在,让我们来看看 TypeScript 提供的一些特性。.
TypeScript 的主要特性
静态类型
静态类型是指在编译时显式声明变量的数据类型(例如整数、字符串、布尔值),并且系统在执行程序之前执行类型检查。.
虽然以下行为在 JavaScript 中是允许的,但在 TypeScript 中执行相同的操作会由于 TypeScript 的类型实现而导致错误。.
let name: string = "hygraph";
name = 2000可选输入
虽然 TypeScript 允许显式声明变量,但它也支持编写类似 JavaScript 的代码而不声明类型。TypeScript 会自动推断类型。例如:
let name = "Hygraph";上面,TypeScript 通过变量初始化值推断类型名称是一个字符串,例如“Hygraph”。.
TypeScript 泛型
通过对类型和函数进行参数化,TypeScript 泛型创建了可重用的组件和函数,这些组件和函数可以处理不同的类型,而不会损害类型安全性:
// Generic function to return the length of an array
function getArrayLength<T>(array: T[]): number {
return array.length;
}
// Using the generic function with different types of arrays
const stringArray: string[] = ["apple", "banana", "orange"];
const numberArray: number[] = [1, 2, 3, 4, 5];
console.log(getArrayLength(stringArray)); // Output: 3
console.log(getArrayLength(numberArray)); // Output: 5泛型通常用于定义需要与树、图和队列等数据类型配合使用的自定义数据类型。.
高级类型系统
TypeScript 类型系统超越了基本的静态类型定义。它还提供了定义复杂类型、操作类型、建立变量间关系、强制类型约束以及其他功能,从而能够实现无错误的应用程序开发。.
让我们来了解一些最常用的高级类型。.
1. 工会的类型
TypeScript 中的联合体(Union)指的是声明一个变量或函数参数,使其包含多种数据类型。当一个值在运行时具有不同的数据类型时,这非常有用。.
联合类型用“|”符号表示,该符号分隔不同的数据类型。例如:
let age = number | string;
age = 10;
age = "ten";如上所示,我们可以指定年龄变量可以有两种数据类型。这既提供了灵活性,又不会牺牲类型安全性。.
2. 交叉路口类型
交叉类型允许将几种现有类型组合成一种新类型。这种新类型具有组合后所有类型的属性和功能。.
使用 & 符号连接要组合的类型,即可创建交集。例如:
interface User {
id: number;
username: string;
email: string;
}
interface Admin {
isAdmin: boolean;
}
// A new type using intersection type
type UserAndAdmin = User & Admin;在这里,“用户和管理员”类型结合了用户界面和管理功能,生成了一个需要两者所有功能的类型。.
3. 条件类型
TypeScript 中的条件类型创建依赖于状态的类型,从而可以定义动态类型,这些类型会根据类型的属性、值或其他上下文而改变。.
我们来看一个简单的例子:
// A conditional type to determine if a type is an array
type IsArray<T> = T extends any[] ? true : false;
// Test the conditional type with different types
type Result1 = IsArray<number>; // false
type Result2 = IsArray<string[]>; // true
type Result3 = IsArray<boolean | []>; // true条件类型使用尖括号 (<>) 中的三元运算符 (? 🙂) 定义,这被称为“泛型类型参数”——我们将在本文后面详细讨论。它们还使用 extends 关键字,该关键字检查类型是否满足特定条件,并根据条件的结果生成另一个类型。.
4. 映射类型
TypeScript 中的映射类型允许你通过转换现有类型的属性来创建新类型。它通过遍历源类型的属性并对每个属性应用转换来实现这一点,从而生成一个新类型。例如:
// type representing a user
type User = {
id: number;
username: string;
email: string;
};
// Mapped type to make all properties optional
type OptionalUser = { [P in keyof User]?: User[P] };
// New type using the mapped type
const optionalUser: OptionalUser = { id: 1 };
// Property 'email' is now optional
optionalUser.username = "john_doe";
// Property 'id' is still required
// optionalUser.email = "[email protected]"; // Error: Property 'email' is missing映射类型使用语法 { [P in keyof Type]: NewType } 定义,其中 Type 是源类型,P 是属性键,NewType 是转换后的类型。P 遍历属性键并定义转换。.
5. 输入昵称
类型别名允许您为现有的 TypeScript 类型创建自定义名称(别名),包括基本类型、联合类型、交叉类型,甚至更复杂的类型,例如对象字面量和函数类型。类型别名使用 `type` 关键字后跟新名称来定义,如下所示:
// type alias for a union type
type Result = "success" | "error";
// type alias for an object literal
type Point = { x: number; y: number };
// type alias for a function type
type Greeting = (name: string) => string;
// Using the type aliases
const status: Result = "success";
const origin: Point = { x: 0, y: 0 };
const greet: Greeting = (name) => Hello, ${name}!;以上代码展示了 TypeScript 中不同类型的类型别名及其在声明后的用法。.
TypeScript 在面向对象编程 (OOP) 中的应用
面向对象编程(OOP)是一种基于“对象”概念的编程范式,通过交互创建可维护和可重用的代码。.
1. TypeScript 类
类是创建对象的模式或设计,也就是说,它们定义了数据(属性)和方法(函数)。.
以下是如何在 TypeScript 中实现类的示例:
class Organization {
private name: string;
private yearFounded: number;
constructor(name: string, yearFounded: number) {
this.name = name;
this.yearFounded = yearFounded;
}
public getDetails(): string {
return `${this.name} was founded in ${this.yearFounded}.`;
}
}
let organization = new Organization("Hygraph", 2015);
console.log(organization.name); // Error: Property 'name' is private and only accessible within class 'Organization'.
console.log(organization.getDetails()); // Output: Hygraph was founded in 2015在上面的代码中,我们创建了一个名为 Organisation 的类,其中包含名为 `yearFounded` 的私有属性,这些属性只能在“Organization”类内部访问和修改。请注意属性和方法的类型定义。.
2. TypeScript 接口
接口通过列出对象必须具备的属性和方法来描述对象的结构,而不提供实现细节:
// Interface representing form data
interface FormData {
firstName: string;
lastName: string;
email: string;
age: number;
}
// Usage
let formData: FormData = {
firstName: "John",
lastName: "Doe",
email: "[email protected]",
age: 30
};在上面的例子中,我们定义了一个 FormData 接口,它表示表单数据的结构。.
接下来,我们创建了一个 formData 对象,其中包含与接口定义相关的属性。.
TypeScript 数字
枚举类型(在 TypeScript 中用 enum 表示)是由花括号 {} 括起来的命名常量集合,其中每个常量都有一个关联的数值或字符串值。.
一个典型的 TypeScript 列表集合可能如下所示:
// enum for days of the week
enum DayOfWeek {
Sunday,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday
}
enum HTTPStatusCodes {
OK = 200,
BadRequest = 400,
NotFound = 404,
}上面的代码块直接解释了正在发生的事情,并展示了为使用 TypeScript 枚举添加语义的好处。.
TypeScript 和 ES6
TypeScript 支持 ECMAScript 6 (ES6)(也称为 ECMAScript 2015)的许多特性。其中一些特性包括:
1)箭头函数:与传统的函数表达式不同,箭头函数提供了一种简洁的函数定义语法。它们为单行表达式提供隐式返回值和自动链式调用,可用于回调函数或事件处理函数。.
// Arrow function
const add = (x, y) => x + y;
// Traditional function expression
const add = function(x, y) {
return x + y;
};2) 模板字母表:此功能允许您将多行表达式和字符串直接嵌入到代码中的花括号 (“) 内。这使得创建动态字符串变得容易,包括插入变量和表达式。.
const name: string = "John";
const greeting: string = `Hello, ${name}!`;ES6 的特性远不止本文所能涵盖。更多信息,请参阅 Ecma International 网站。.
TypeScript 相对于 JavaScript 的优势
自 TypeScript 发布十多年以来,关于它相对于 JavaScript 的优势一直存在争论。.
在本节中,我们将探讨其中的一些好处。.
- 安全类型: TypeScript 的静态类型系统将类型注解应用于变量、函数和对象,这有助于及早发现错误,并通过接口、类和模块提高可维护性。.
- 更好的开发者体验: 开发者现在可以更加自信地编写代码,因为他们知道编译器会在代码运行时之前检测到潜在的类型不匹配问题。这在将 JavaScript 代码库迁移到 TypeScript 时尤其有用。.
何时使用 TypeScript
从以上权衡可以看出,TypeScript 可能并不适合所有项目。这或许没错,但为什么要把这个决定权留给自己呢?让我们来帮您做出更明智的选择。.
什么时候适合使用 TypeScript?
- 大规模应用: TypeScript 的开发旨在解决大型 JavaScript 代码库的可扩展性问题。随着项目的增长,静态类型有助于及早发现错误,从而提高代码的可维护性以及团队成员之间的协作效率。.
- 团队合作: 在多个开发人员共同编写代码库的团队环境中,TypeScript 可以通过强制执行编码规范和通过自文档化代码实现更好的沟通来促进协作。.
- 长期项目: 维护是软件开发生命周期的最后一个阶段,持续时间可长达十年,也可短至一年。TypeScript 适用于长期项目,在这些项目中,代码的可维护性、可扩展性和面向未来的适应性至关重要。.
何时不应使用 TypeScript
遗憾的是,尽管 TypeScript 有诸多优点,但它可能并不适用于所有使用场景。例如:
- 简单项目: 对于复杂度极低的小型项目而言,静态类型和高级工具带来的好处可能不足以抵消 TypeScript 的配置和学习曲线。.
- 旧代码库: 将大型现有 JavaScript 代码库转换为 TypeScript 可能是一项艰巨的任务。在这种情况下,迁移到 TypeScript 所需的工作量可能不足以弥补其带来的收益,尤其是在项目接近生命周期末期或维护工作量极少的情况下。.









