原文:https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html

下面是本人对官方文档TypeScript for JavaScript Programmers的翻译。

TypeScript stands in an unusual relationship to JavaScript. TypeScript offers all of JavaScript’s features, and an additional layer on top of these: TypeScript’s type system.

TypeScript与JavaScript有着不同寻常的关系。TypeScript提供了JavaScript的所有特性,并在这些特性之上增加了一层: TypeScript的类型系统。

For example, JavaScript provides language primitives like string, number, and object, but it doesn’t check that you’ve consistently assigned these. TypeScript does.

例如,JavaScript提供了stringnumberobject等语言原语,但它不会检查您是否一致地分配了这些原语。TypeScript做到了。

This means that your existing working JavaScript code is also TypeScript code. The main benefit of TypeScript is that it can highlight unexpected behavior in your code, lowering the chance of bugs.

这意味着您现有可以工作的JavaScript代码也是TypeScript代码。TypeScript的主要好处是它可以突出显示代码中的意外行为,从而降低了出现错误的机会。

This tutorial provides a brief overview of TypeScript, focusing on its type system.

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

Types by Inference(推理类型)

TypeScript knows the JavaScript language and will generate types for you in many cases. For example in creating a variable and assigning it to a particular value, TypeScript will use the value as its type.

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

  1. let helloWorld = "Hello World";
  2. // ^ = let helloWorld: string

By understanding how JavaScript works, TypeScript can build a type-system that accepts JavaScript code but has types. This offers a type-system without needing to add extra characters to make types explicit in your code. That’s how TypeScript knows that helloWorld is a string in the above example.

通过了解JavaScript的工作原理,TypeScript可以构建一个接受JavaScript代码但具有类型的类型系统。他不需要添加额外的字符来使类型在代码中显式。在上面的例子中,TypeScript就是这样知道helloWorld是一个字符串的。

You may have written JavaScript in Visual Studio Code, and had editor auto-completion. Visual Studio Code uses TypeScript under the hood to make it easier to work with JavaScript.

您可能已经用Visual Studio代码编写了JavaScript,并具有编辑器自动完成功能。Visual Studio Code在后台使用TypeScript使其更易于使用JavaScript。

Defining Types(定义类型)

You can use a wide variety of design patterns in JavaScript. However, some design patterns make it difficult for types to be inferred automatically (for example, patterns that use dynamic programming). To cover these cases, TypeScript supports an extension of the JavaScript language, which offers places for you to tell TypeScript what the types should be.

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

For example, to create an object with an inferred type which includes name: string and id: number, you can write:

例如,要创建具有推断类型 (包括name: stringid: number) 的对象,您可以编写:

  1. const user = {
  2. name: "Hayes",
  3. id: 0,
  4. };

You can explicitly describe this object’s shape using an interface declaration:

您可以使用接口声明显式描述此对象:

  1. interface User {
  2. name: string;
  3. id: number;
  4. }

You can then declare that a JavaScript object conforms to the shape of your new interface by using syntax like : TypeName after a variable declaration:

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

  1. const user: User = {
  2. name: "Hayes",
  3. id: 0,
  4. };

If you provide an object that doesn’t match the interface you have provided, TypeScript will warn you:

如果您提供的对象与您提供的接口不匹配,TypeScript将警告您:

  1. interface User {
  2. name: string;
  3. id: number;
  4. }
  5. const user: User = {
  6. username: "Hayes",
  7. id: 0,
  8. };
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’.

Since JavaScript supports classes and object-oriented programming, so does TypeScript. You can use an interface declaration with classes:

由于JavaScript支持类和面向对象的编程,TypeScript也是如此。您可以对类使用接口声明:

  1. interface User {
  2. name: string;
  3. id: number;
  4. }
  5. class UserAccount {
  6. name: string;
  7. id: number;
  8. constructor(name: string, id: number) {
  9. this.name = name;
  10. this.id = id;
  11. }
  12. }
  13. const user: User = new UserAccount("Murphy", 1);

You can use interfaces to annotate parameters and return values to functions:

您可以使用接口为函数注释参数和返回值:

  1. function getAdminUser(): User {
  2. //...
  3. }
  4. function deleteUser(user: User) {
  5. // ...
  6. }

There are already a small set of primitive types available in JavaScript: boolean, bigint, null, number, string, symbol, object, and undefined, which you can use in an interface. TypeScript extends this list with a few more, such as any (allow anything), unknown (ensure someone using this type declares what the type is), never (it’s not possible that this type could happen), and void (a function which returns undefined or has no return value).

JavaScript中已经有一小部分原始类型可用: booleanbigintnullnumberstringsymbolobjectundefined,可在接口中使用。TypeScript进一步扩展了此列表,例如any (允许任何内容) 、unknown (确保使用此类型的人声明类型是什么),never (不可能发生这种类型) 和void (返回undefined或没有返回值的函数)。

You’ll see that there are two syntaxes for building types: Interfaces and Types. You should prefer interface. Use type when you need specific features.

您将看到构建类型有两种语法: Interfaces and Types.。您应该更喜欢interface。需要特定功能时使用type

Composing Types(组合类型)

With TypeScript, you can create complex types by combining simple ones. There are two popular ways to do so: with Unions, and with Generics.

使用TypeScript,您可以通过组合简单的类型来创建复杂的类型。有两种流行的方法: Union和Generics(范型)。

Unions(联合)

With a union, you can declare that a type could be one of many types. For example, you can describe a boolean type as being either true or false:

使用union,您可以声明许多类型。例如,您可以把一个boolean类型描述为truefalse:

  1. type MyBool = true | false;

Note: If you hover over MyBool above, you’ll see that it is classed as boolean. That’s a property of the Structural Type System. More on this below.

注意: 如果将鼠标悬停在上面的MyBool上,您会看到它被归类为布尔值。这是结构型系统的一个特性。更多信息如下。

A popular use-case for union types is to describe the set of strings or numbers literal that a value is allowed to be:

union类型的一个比较流行用例是描述的string集合或number字面量的许可值:

  1. type WindowStates = "open" | "closed" | "minimized";
  2. type LockStates = "locked" | "unlocked";
  3. type OddNumbersUnderTen = 1 | 3 | 5 | 7 | 9;

(译者注:那就是说可以把具有代码表作用的枚举变量定义成独立的类型了)

Unions provide a way to handle different types too. For example, you may have a function that takes an array or a string:

union也提供了一种处理不同类型的方法。例如,您可能有一个接受数组或字符串做参数的函数:

  1. function getLength(obj: string | string[]) {
  2. return obj.length;
  3. }

To learn the type of a variable, use typeof:

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

Type Predicate
string typeof s === "string"
number typeof n === "number"
boolean typeof b === "boolean"
undefined typeof undefined === "undefined"
function typeof f === "function"
array Array.isArray(a)

For example, you can make a function return different values depending on whether it is passed a string or an array:

例如,您可以根据传递的是字符串还是数组,使函数返回不同的值:

  1. function wrapInArray(obj: string | string[]) {
  2. if (typeof obj === "string") {
  3. return [obj];
  4. // ^ = (parameter) obj: string
  5. } else {
  6. return obj;
  7. }
  8. }

Generics(泛型)

A common example is an array. An array without generics could contain anything. An array with generics can describe the values that the array contains.

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

  1. type StringArray = Array<string>;
  2. type NumberArray = Array<number>;
  3. type ObjectWithNameArray = Array<{ name: string }>;

You can declare your own types that use generics:

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

  1. interface Backpack<Type> {
  2. add: (obj: Type) => void;
  3. get: () => Type;
  4. }
  5. // This line is a shortcut to tell TypeScript there is a
  6. // constant called `backpack`, and to not worry about where it came from.
  7. declare const backpack: Backpack<string>;
  8. // object is a string, because we declared it above as the variable part of Backpack.
  9. const object = backpack.get();
  10. // Since the backpack variable is a string, you can't pass a number to the add function.
  11. backpack.add(23);

backpack.add(23);

Argument of type ‘number’ is not assignable to parameter of type ‘string’.


Structural Type System(结构式类型系统)

One of TypeScript’s core principles is that type checking focuses on the shape that values have. This is sometimes called “duck typing” or “structural typing”.

TypeScript的核心原则之一是视值的样式/形状进行类型检测。有时候这被称为 “鸭子类型” 或 “结构化类型”。

In a structural type system, if two objects have the same shape, they are considered to be of the same type.

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

  1. interface Point {
  2. x: number;
  3. y: number;
  4. }
  5. function logPoint(p: Point) {
  6. console.log(`${p.x}, ${p.y}`);
  7. }
  8. // logs "12, 26"
  9. const point = { x: 12, y: 26 };
  10. logPoint(point);

The point variable is never declared to be a Point type. However, TypeScript compares the shape of point to the shape of Point in the type-check. They have the same shape, so the code passes.

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

The shape-matching only requires a subset of the object’s fields to match.

样式匹配仅需要对象字段的子集进行匹配。

  1. const point3 = { x: 12, y: 26, z: 89 };
  2. logPoint(point3); // logs "12, 26"
  3. const rect = { x: 33, y: 3, width: 30, height: 80 };
  4. logPoint(rect); // logs "33, 3"
  5. const color = { hex: "#187ABF" };
  6. 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, y

There is no difference between how classes and objects conform to shapes:

类和对象确认样式的方式没有区别:

  1. class VirtualPoint {
  2. x: number;
  3. y: number;
  4. constructor(x: number, y: number) {
  5. this.x = x;
  6. this.y = y;
  7. }
  8. }
  9. const newVPoint = new VirtualPoint(13, 56);
  10. logPoint(newVPoint); // logs "13, 56"

If the object or class has all the required properties, TypeScript will say they match, regardless of the implementation details.

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