面向 JavaScript 程序员的 TypeScript

TypeScript 与 JavaScript 的关系非同寻常。TypeScript 提供了 JavaScript 的所有功能,并在其基础上增加了一层:TypeScript 的类型系统。

例如,JavaScript 提供了像 stringnumber 这样的语言基元,但它不会检查您是否始终如一地分配这些基元。TypeScript 会检查。

这意味着您现有的可运行 JavaScript 代码也是 TypeScript 代码。TypeScript 的主要好处是它可以突出显示代码中意外的行为,降低出现错误的可能性。

本教程简要概述了 TypeScript,重点介绍了它的类型系统。

通过推断的类型

TypeScript 了解 JavaScript 语言,并且在许多情况下会为您生成类型。例如,在创建变量并将其分配给特定值时,TypeScript 会将该值用作其类型。

ts
let helloWorld = "Hello World";
let helloWorld: string
Try

通过了解 JavaScript 的工作原理,TypeScript 可以构建一个接受 JavaScript 代码但具有类型的类型系统。这提供了一个类型系统,而无需在代码中添加额外的字符来明确类型。这就是 TypeScript 知道在上述示例中 helloWorldstring 的方式。

您可能在 Visual Studio Code 中编写了 JavaScript,并且具有编辑器自动完成功能。Visual Studio Code 在后台使用 TypeScript,以便更轻松地使用 JavaScript。

定义类型

您可以在 JavaScript 中使用各种设计模式。但是,某些设计模式使得难以自动推断类型(例如,使用动态编程的模式)。为了涵盖这些情况,TypeScript 支持 JavaScript 语言的扩展,该扩展为您提供了告诉 TypeScript 类型应该是什么的位置。

例如,要创建一个包含 name: stringid: number 的推断类型对象,可以编写

ts
const user = {
name: "Hayes",
id: 0,
};
Try

可以使用 interface 声明明确描述此对象的形状

ts
interface User {
name: string;
id: number;
}
Try

然后可以通过在变量声明后使用 : TypeName 等语法声明 JavaScript 对象符合新 interface 的形状

ts
const user: User = {
name: "Hayes",
id: 0,
};
Try

如果您提供与您提供的接口不匹配的对象,TypeScript 会向您发出警告

ts
interface User {
name: string;
id: number;
}
 
const user: User = {
username: "Hayes",
Type '{ username: string; id: number; }' is not assignable to type 'User'. Object literal may only specify known properties, and 'username' does not exist in type 'User'.2322Type '{ username: string; id: number; }' is not assignable to type 'User'. Object literal may only specify known properties, and 'username' does not exist in type 'User'.
id: 0,
};
Try

由于 JavaScript 支持类和面向对象编程,因此 TypeScript 也支持。您可以在类中使用接口声明

ts
interface User {
name: string;
id: number;
}
 
class UserAccount {
name: string;
id: number;
 
constructor(name: string, id: number) {
this.name = name;
this.id = id;
}
}
 
const user: User = new UserAccount("Murphy", 1);
Try

可以使用接口为函数的参数和返回值添加注释

ts
function deleteUser(user: User) {
// ...
}
 
function getAdminUser(): User {
//...
}
Try

JavaScript 中已经有一组可用的基本类型:booleanbigintnullnumberstringsymbolundefined,您可以在接口中使用这些类型。TypeScript 使用 any(允许任何内容)、unknown(确保使用此类型的人声明类型)、never(不可能发生此类型)和 void(返回 undefined 或没有返回值的函数)等类型扩展了此列表。

您会看到有两种用于构建类型的语法:接口和类型。您应该优先使用 interface。当您需要特定功能时,请使用 type

组合类型

使用 TypeScript,您可以通过组合简单类型来创建复杂类型。有两种流行的方法可以做到这一点:使用联合类型和使用泛型。

联合

使用联合,你可以声明一个类型可以是多种类型之一。例如,你可以将一个 boolean 类型描述为 truefalse

ts
type MyBool = true | false;
Try

注意:如果你将鼠标悬停在上面的 MyBool 上,你会看到它被归类为 boolean。这是结构化类型系统的属性。下面会详细介绍。

联合类型的流行用例是描述一个值允许为 stringnumber 字面量 的集合

ts
type WindowStates = "open" | "closed" | "minimized";
type LockStates = "locked" | "unlocked";
type PositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
Try

联合也提供了一种处理不同类型的方法。例如,你可能有一个接受 arraystring 的函数

ts
function getLength(obj: string | string[]) {
return obj.length;
}
Try

要了解变量的类型,请使用 typeof

类型 谓词
string typeof s === "string"
number typeof n === "number"
boolean typeof b === "boolean"
undefined typeof undefined === "undefined"
function typeof f === "function"
array Array.isArray(a)

例如,你可以根据函数是传递字符串还是数组来让它返回不同的值

ts
function wrapInArray(obj: string | string[]) {
if (typeof obj === "string") {
return [obj];
(parameter) obj: string
}
return obj;
}
Try

泛型

泛型为类型提供变量。一个常见的例子是数组。没有泛型的数组可以包含任何内容。有泛型的数组可以描述数组包含的值。

ts
type StringArray = Array<string>;
type NumberArray = Array<number>;
type ObjectWithNameArray = Array<{ name: string }>;

你可以声明你自己的使用泛型的类型

ts
interface Backpack<Type> {
add: (obj: Type) => void;
get: () => Type;
}
 
// This line is a shortcut to tell TypeScript there is a
// constant called `backpack`, and to not worry about where it came from.
declare const backpack: Backpack<string>;
 
// object is a string, because we declared it above as the variable part of Backpack.
const object = backpack.get();
 
// Since the backpack variable is a string, you can't pass a number to the add function.
backpack.add(23);
Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.
Try

结构类型系统

TypeScript 的核心原则之一是类型检查专注于值所具有的形状。这有时称为“鸭子类型”或“结构类型”。

在结构类型系统中,如果两个对象具有相同的形状,则它们被认为是同一种类型。

ts
interface Point {
x: number;
y: number;
}
 
function logPoint(p: Point) {
console.log(`${p.x}, ${p.y}`);
}
 
// logs "12, 26"
const point = { x: 12, y: 26 };
logPoint(point);
Try

point 变量从未被声明为 Point 类型。但是,TypeScript 在类型检查中将 point 的形状与 Point 的形状进行比较。它们具有相同的形状,因此代码通过。

形状匹配仅要求对象字段的子集匹配。

ts
const point3 = { x: 12, y: 26, z: 89 };
logPoint(point3); // logs "12, 26"
 
const rect = { x: 33, y: 3, width: 30, height: 80 };
logPoint(rect); // logs "33, 3"
 
const color = { hex: "#187ABF" };
logPoint(color);
Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, y2345Argument of type '{ hex: string; }' is not assignable to parameter of type 'Point'. Type '{ hex: string; }' is missing the following properties from type 'Point': x, y
Try

类和对象如何符合形状之间没有区别

ts
class VirtualPoint {
x: number;
y: number;
 
constructor(x: number, y: number) {
this.x = x;
this.y = y;
}
}
 
const newVPoint = new VirtualPoint(13, 56);
logPoint(newVPoint); // logs "13, 56"
Try

如果对象或类具有所有必需的属性,则 TypeScript 会说它们匹配,而不管实现细节如何。

下一步

这是日常 TypeScript 中使用的语法和工具的简要概述。在此基础上,你可以

TypeScript 文档是一个开源项目。通过发送拉取请求帮助我们改进这些页面 ❤

本页面的贡献者
OTOrta Therox (24)
DSDustin Stender (1)
MKMatt Kantor (1)
JCRJuan Carlos Ruiz (1)
IOIván Ovejero (1)
18+

上次更新时间:2024 年 3 月 21 日