TypeScript 与 JavaScript 的关系非同寻常。TypeScript 提供了 JavaScript 的所有功能,并在其基础上增加了一层:TypeScript 的类型系统。
例如,JavaScript 提供了像 string
和 number
这样的语言基元,但它不会检查您是否始终如一地分配这些基元。TypeScript 会检查。
这意味着您现有的可运行 JavaScript 代码也是 TypeScript 代码。TypeScript 的主要好处是它可以突出显示代码中意外的行为,降低出现错误的可能性。
本教程简要概述了 TypeScript,重点介绍了它的类型系统。
通过推断的类型
TypeScript 了解 JavaScript 语言,并且在许多情况下会为您生成类型。例如,在创建变量并将其分配给特定值时,TypeScript 会将该值用作其类型。
tsTry
lethelloWorld = "Hello World";
通过了解 JavaScript 的工作原理,TypeScript 可以构建一个接受 JavaScript 代码但具有类型的类型系统。这提供了一个类型系统,而无需在代码中添加额外的字符来明确类型。这就是 TypeScript 知道在上述示例中 helloWorld
是 string
的方式。
您可能在 Visual Studio Code 中编写了 JavaScript,并且具有编辑器自动完成功能。Visual Studio Code 在后台使用 TypeScript,以便更轻松地使用 JavaScript。
定义类型
您可以在 JavaScript 中使用各种设计模式。但是,某些设计模式使得难以自动推断类型(例如,使用动态编程的模式)。为了涵盖这些情况,TypeScript 支持 JavaScript 语言的扩展,该扩展为您提供了告诉 TypeScript 类型应该是什么的位置。
例如,要创建一个包含 name: string
和 id: number
的推断类型对象,可以编写
tsTry
constuser = {name : "Hayes",id : 0,};
可以使用 interface
声明明确描述此对象的形状
tsTry
interfaceUser {name : string;id : number;}
然后可以通过在变量声明后使用 : TypeName
等语法声明 JavaScript 对象符合新 interface
的形状
tsTry
constuser :User = {name : "Hayes",id : 0,};
如果您提供与您提供的接口不匹配的对象,TypeScript 会向您发出警告
tsTry
interfaceUser {name : string;id : number;}constuser :User = {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'.username : "Hayes",id : 0,};
由于 JavaScript 支持类和面向对象编程,因此 TypeScript 也支持。您可以在类中使用接口声明
tsTry
interfaceUser {name : string;id : number;}classUserAccount {name : string;id : number;constructor(name : string,id : number) {this.name =name ;this.id =id ;}}constuser :User = newUserAccount ("Murphy", 1);
可以使用接口为函数的参数和返回值添加注释
tsTry
functiondeleteUser (user :User ) {// ...}functiongetAdminUser ():User {//...}
JavaScript 中已经有一组可用的基本类型:boolean
、bigint
、null
、number
、string
、symbol
和 undefined
,您可以在接口中使用这些类型。TypeScript 使用 any
(允许任何内容)、unknown
(确保使用此类型的人声明类型)、never
(不可能发生此类型)和 void
(返回 undefined
或没有返回值的函数)等类型扩展了此列表。
您会看到有两种用于构建类型的语法:接口和类型。您应该优先使用 interface
。当您需要特定功能时,请使用 type
。
组合类型
使用 TypeScript,您可以通过组合简单类型来创建复杂类型。有两种流行的方法可以做到这一点:使用联合类型和使用泛型。
联合
使用联合,你可以声明一个类型可以是多种类型之一。例如,你可以将一个 boolean
类型描述为 true
或 false
tsTry
typeMyBool = true | false;
注意:如果你将鼠标悬停在上面的 MyBool
上,你会看到它被归类为 boolean
。这是结构化类型系统的属性。下面会详细介绍。
联合类型的流行用例是描述一个值允许为 string
或 number
字面量 的集合
tsTry
typeWindowStates = "open" | "closed" | "minimized";typeLockStates = "locked" | "unlocked";typePositiveOddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;
联合也提供了一种处理不同类型的方法。例如,你可能有一个接受 array
或 string
的函数
tsTry
functiongetLength (obj : string | string[]) {returnobj .length ;}
要了解变量的类型,请使用 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) |
例如,你可以根据函数是传递字符串还是数组来让它返回不同的值
tsTry
functionwrapInArray (obj : string | string[]) {if (typeofobj === "string") {return [obj ];}returnobj ;}
泛型
泛型为类型提供变量。一个常见的例子是数组。没有泛型的数组可以包含任何内容。有泛型的数组可以描述数组包含的值。
ts
type StringArray = Array<string>;type NumberArray = Array<number>;type ObjectWithNameArray = Array<{ name: string }>;
你可以声明你自己的使用泛型的类型
tsTry
interfaceBackpack <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 constbackpack :Backpack <string>;// object is a string, because we declared it above as the variable part of Backpack.constobject =backpack .get ();// Since the backpack variable is a string, you can't pass a number to the add function.Argument of type 'number' is not assignable to parameter of type 'string'.2345Argument of type 'number' is not assignable to parameter of type 'string'.backpack .add (23 );
结构类型系统
TypeScript 的核心原则之一是类型检查专注于值所具有的形状。这有时称为“鸭子类型”或“结构类型”。
在结构类型系统中,如果两个对象具有相同的形状,则它们被认为是同一种类型。
tsTry
interfacePoint {x : number;y : number;}functionlogPoint (p :Point ) {console .log (`${p .x }, ${p .y }`);}// logs "12, 26"constpoint = {x : 12,y : 26 };logPoint (point );
point
变量从未被声明为 Point
类型。但是,TypeScript 在类型检查中将 point
的形状与 Point
的形状进行比较。它们具有相同的形状,因此代码通过。
形状匹配仅要求对象字段的子集匹配。
tsTry
constpoint3 = {x : 12,y : 26,z : 89 };logPoint (point3 ); // logs "12, 26"constrect = {x : 33,y : 3,width : 30,height : 80 };logPoint (rect ); // logs "33, 3"constcolor = {hex : "#187ABF" };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, ylogPoint (); color
类和对象如何符合形状之间没有区别
tsTry
classVirtualPoint {x : number;y : number;constructor(x : number,y : number) {this.x =x ;this.y =y ;}}constnewVPoint = newVirtualPoint (13, 56);logPoint (newVPoint ); // logs "13, 56"
如果对象或类具有所有必需的属性,则 TypeScript 会说它们匹配,而不管实现细节如何。
下一步
这是日常 TypeScript 中使用的语法和工具的简要概述。在此基础上,你可以