From 85e6bdb5152b672f2581e06315ac945a2155935e Mon Sep 17 00:00:00 2001 From: zhouLion Date: Tue, 7 Sep 2021 23:41:57 +0800 Subject: [PATCH 01/15] ZH translation: pull documentation en version files TODO: to translate these --- .../zh/declaration-files/By Example.md | 251 + .../zh/declaration-files/Consumption.md | 44 + .../zh/declaration-files/Deep Dive.md | 232 + .../zh/declaration-files/Do's and Don'ts.md | 241 + .../zh/declaration-files/Introduction.md | 53 + .../declaration-files/Library Structures.md | 326 + .../zh/declaration-files/Publishing.md | 182 + .../zh/declaration-files/Templates.md | 15 + .../templates/global-modifying-module.d.ts.md | 72 + .../templates/global-plugin.d.ts.md | 307 + .../templates/global.d.ts.md | 144 + .../templates/module-class.d.ts.md | 83 + .../templates/module-function.d.ts.md | 85 + .../templates/module-plugin.d.ts.md | 67 + .../templates/module.d.ts.md | 311 + .../TS for Functional Programmers.md | 597 + .../zh/get-started/TS for JS Programmers.md | 289 + .../zh/get-started/TS for OOPers.md | 194 + .../get-started/TS for the New Programmer.md | 194 + .../zh/handbook-v1/Basic Types.md | 417 + docs/documentation/zh/handbook-v1/Classes.md | 611 + .../documentation/zh/handbook-v1/Functions.md | 546 + docs/documentation/zh/handbook-v1/Generics.md | 376 + .../zh/handbook-v1/Interfaces.md | 717 ++ .../zh/handbook-v1/Literal Types.md | 120 + .../handbook-v1/Unions and Intersections.md | 412 + docs/documentation/zh/handbook-v2/Basics.md | 440 + docs/documentation/zh/handbook-v2/Classes.md | 1414 +++ .../zh/handbook-v2/Everyday Types.md | 714 ++ docs/documentation/zh/handbook-v2/Modules.md | 385 + .../zh/handbook-v2/More on Functions.md | 867 ++ .../documentation/zh/handbook-v2/Narrowing.md | 769 ++ .../zh/handbook-v2/Object Types.md | 948 ++ .../zh/handbook-v2/The Handbook.md | 59 + .../zh/handbook-v2/Type Declarations.md | 100 + .../Type Manipulation/Conditional Types.md | 271 + .../handbook-v2/Type Manipulation/Generics.md | 376 + .../Type Manipulation/Indexed Access Types.md | 77 + .../Type Manipulation/Keyof Type Operator.md | 32 + .../Type Manipulation/Mapped Types.md | 146 + .../Template Literal Types.md | 217 + .../Type Manipulation/Typeof Type Operator.md | 70 + .../_Creating Types from Types.md | 22 + .../zh/handbook-v2/Understanding Errors.md | 71 + .../javascript/Creating DTS files From JS.md | 88 + .../zh/javascript/Intro to JS with TS.md | 70 + .../zh/javascript/JSDoc Reference.md | 708 ++ .../Type Checking JavaScript Files.md | 310 + .../Compiler Options in MSBuild.md | 600 + .../zh/project-config/Compiler Options.md | 1147 ++ .../zh/project-config/Configuring Watch.md | 74 + .../Integrating with Build Tools.md | 270 + .../zh/project-config/Project References.md | 222 + .../zh/reference/Advanced Types.md | 1201 ++ .../zh/reference/Declaration Merging.md | 330 + docs/documentation/zh/reference/Decorators.md | 607 + docs/documentation/zh/reference/Enums.md | 419 + .../zh/reference/Iterators and Generators.md | 100 + docs/documentation/zh/reference/JSX.md | 444 + docs/documentation/zh/reference/Mixins.md | 274 + .../zh/reference/Module Resolution.md | 459 + docs/documentation/zh/reference/Modules.md | 919 ++ .../zh/reference/Namespaces and Modules.md | 128 + docs/documentation/zh/reference/Namespaces.md | 281 + docs/documentation/zh/reference/Symbols.md | 107 + .../zh/reference/Triple-Slash Directives.md | 144 + .../zh/reference/Type Compatibility.md | 404 + .../zh/reference/Type Inference.md | 163 + .../zh/reference/Utility Types.md | 505 + .../zh/reference/Variable Declarations.md | 706 ++ .../zh/release-notes/Overview.md | 10423 ++++++++++++++++ .../zh/release-notes/TypeScript 1.1.md | 28 + .../zh/release-notes/TypeScript 1.3.md | 55 + .../zh/release-notes/TypeScript 1.4.md | 261 + .../zh/release-notes/TypeScript 1.5.md | 393 + .../zh/release-notes/TypeScript 1.6.md | 462 + .../zh/release-notes/TypeScript 1.7.md | 214 + .../zh/release-notes/TypeScript 1.8.md | 600 + .../zh/release-notes/TypeScript 2.0.md | 944 ++ .../zh/release-notes/TypeScript 2.1.md | 522 + .../zh/release-notes/TypeScript 2.2.md | 212 + .../zh/release-notes/TypeScript 2.3.md | 195 + .../zh/release-notes/TypeScript 2.4.md | 170 + .../zh/release-notes/TypeScript 2.5.md | 47 + .../zh/release-notes/TypeScript 2.6.md | 273 + .../zh/release-notes/TypeScript 2.7.md | 393 + .../zh/release-notes/TypeScript 2.8.md | 427 + .../zh/release-notes/TypeScript 2.9.md | 336 + .../zh/release-notes/TypeScript 3.0.md | 356 + .../zh/release-notes/TypeScript 3.1.md | 76 + .../zh/release-notes/TypeScript 3.2.md | 224 + .../zh/release-notes/TypeScript 3.3.md | 118 + .../zh/release-notes/TypeScript 3.4.md | 437 + .../zh/release-notes/TypeScript 3.5.md | 230 + .../zh/release-notes/TypeScript 3.6.md | 342 + .../zh/release-notes/TypeScript 3.7.md | 849 ++ .../zh/release-notes/TypeScript 3.8.md | 454 + .../zh/release-notes/TypeScript 3.9.md | 543 + .../zh/release-notes/TypeScript 4.0.md | 738 ++ .../zh/release-notes/TypeScript 4.1.md | 654 + .../zh/release-notes/TypeScript 4.2.md | 681 + .../zh/release-notes/TypeScript 4.3.md | 865 ++ .../zh/release-notes/TypeScript 4.4.md | 678 + .../zh/tutorials/ASP.NET Core.md | 215 + docs/documentation/zh/tutorials/Angular.md | 14 + .../zh/tutorials/Babel with TypeScript.md | 49 + .../zh/tutorials/DOM Manipulation.md | 201 + docs/documentation/zh/tutorials/Gulp.md | 467 + .../zh/tutorials/Migrating from JavaScript.md | 442 + docs/documentation/zh/tutorials/React.md | 26 + .../TypeScript Tooling in 5 minutes.md | 187 + 111 files changed, 49345 insertions(+) create mode 100644 docs/documentation/zh/declaration-files/By Example.md create mode 100644 docs/documentation/zh/declaration-files/Consumption.md create mode 100644 docs/documentation/zh/declaration-files/Deep Dive.md create mode 100644 docs/documentation/zh/declaration-files/Do's and Don'ts.md create mode 100644 docs/documentation/zh/declaration-files/Introduction.md create mode 100644 docs/documentation/zh/declaration-files/Library Structures.md create mode 100644 docs/documentation/zh/declaration-files/Publishing.md create mode 100644 docs/documentation/zh/declaration-files/Templates.md create mode 100644 docs/documentation/zh/declaration-files/templates/global-modifying-module.d.ts.md create mode 100644 docs/documentation/zh/declaration-files/templates/global-plugin.d.ts.md create mode 100644 docs/documentation/zh/declaration-files/templates/global.d.ts.md create mode 100644 docs/documentation/zh/declaration-files/templates/module-class.d.ts.md create mode 100644 docs/documentation/zh/declaration-files/templates/module-function.d.ts.md create mode 100644 docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md create mode 100644 docs/documentation/zh/declaration-files/templates/module.d.ts.md create mode 100644 docs/documentation/zh/get-started/TS for Functional Programmers.md create mode 100644 docs/documentation/zh/get-started/TS for JS Programmers.md create mode 100644 docs/documentation/zh/get-started/TS for OOPers.md create mode 100644 docs/documentation/zh/get-started/TS for the New Programmer.md create mode 100644 docs/documentation/zh/handbook-v1/Basic Types.md create mode 100644 docs/documentation/zh/handbook-v1/Classes.md create mode 100644 docs/documentation/zh/handbook-v1/Functions.md create mode 100644 docs/documentation/zh/handbook-v1/Generics.md create mode 100644 docs/documentation/zh/handbook-v1/Interfaces.md create mode 100644 docs/documentation/zh/handbook-v1/Literal Types.md create mode 100644 docs/documentation/zh/handbook-v1/Unions and Intersections.md create mode 100644 docs/documentation/zh/handbook-v2/Basics.md create mode 100644 docs/documentation/zh/handbook-v2/Classes.md create mode 100644 docs/documentation/zh/handbook-v2/Everyday Types.md create mode 100644 docs/documentation/zh/handbook-v2/Modules.md create mode 100644 docs/documentation/zh/handbook-v2/More on Functions.md create mode 100644 docs/documentation/zh/handbook-v2/Narrowing.md create mode 100644 docs/documentation/zh/handbook-v2/Object Types.md create mode 100644 docs/documentation/zh/handbook-v2/The Handbook.md create mode 100644 docs/documentation/zh/handbook-v2/Type Declarations.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/Keyof Type Operator.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md create mode 100644 docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md create mode 100644 docs/documentation/zh/handbook-v2/Understanding Errors.md create mode 100644 docs/documentation/zh/javascript/Creating DTS files From JS.md create mode 100644 docs/documentation/zh/javascript/Intro to JS with TS.md create mode 100644 docs/documentation/zh/javascript/JSDoc Reference.md create mode 100644 docs/documentation/zh/javascript/Type Checking JavaScript Files.md create mode 100644 docs/documentation/zh/project-config/Compiler Options in MSBuild.md create mode 100644 docs/documentation/zh/project-config/Compiler Options.md create mode 100644 docs/documentation/zh/project-config/Configuring Watch.md create mode 100644 docs/documentation/zh/project-config/Integrating with Build Tools.md create mode 100644 docs/documentation/zh/project-config/Project References.md create mode 100644 docs/documentation/zh/reference/Advanced Types.md create mode 100644 docs/documentation/zh/reference/Declaration Merging.md create mode 100644 docs/documentation/zh/reference/Decorators.md create mode 100644 docs/documentation/zh/reference/Enums.md create mode 100644 docs/documentation/zh/reference/Iterators and Generators.md create mode 100644 docs/documentation/zh/reference/JSX.md create mode 100644 docs/documentation/zh/reference/Mixins.md create mode 100644 docs/documentation/zh/reference/Module Resolution.md create mode 100644 docs/documentation/zh/reference/Modules.md create mode 100644 docs/documentation/zh/reference/Namespaces and Modules.md create mode 100644 docs/documentation/zh/reference/Namespaces.md create mode 100644 docs/documentation/zh/reference/Symbols.md create mode 100644 docs/documentation/zh/reference/Triple-Slash Directives.md create mode 100644 docs/documentation/zh/reference/Type Compatibility.md create mode 100644 docs/documentation/zh/reference/Type Inference.md create mode 100644 docs/documentation/zh/reference/Utility Types.md create mode 100644 docs/documentation/zh/reference/Variable Declarations.md create mode 100644 docs/documentation/zh/release-notes/Overview.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 1.1.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 1.3.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 1.4.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 1.5.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 1.6.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 1.7.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 1.8.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.0.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.1.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.2.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.3.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.4.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.5.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.6.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.7.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.8.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 2.9.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.0.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.1.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.2.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.3.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.4.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.5.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.6.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.7.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.8.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 3.9.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 4.0.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 4.1.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 4.2.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 4.3.md create mode 100644 docs/documentation/zh/release-notes/TypeScript 4.4.md create mode 100644 docs/documentation/zh/tutorials/ASP.NET Core.md create mode 100644 docs/documentation/zh/tutorials/Angular.md create mode 100644 docs/documentation/zh/tutorials/Babel with TypeScript.md create mode 100755 docs/documentation/zh/tutorials/DOM Manipulation.md create mode 100644 docs/documentation/zh/tutorials/Gulp.md create mode 100644 docs/documentation/zh/tutorials/Migrating from JavaScript.md create mode 100644 docs/documentation/zh/tutorials/React.md create mode 100644 docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md diff --git a/docs/documentation/zh/declaration-files/By Example.md b/docs/documentation/zh/declaration-files/By Example.md new file mode 100644 index 00000000..6717d697 --- /dev/null +++ b/docs/documentation/zh/declaration-files/By Example.md @@ -0,0 +1,251 @@ +--- +title: Declaration Reference +layout: docs +permalink: /docs/handbook/declaration-files/by-example.html +oneline: "How to create a d.ts file for a module" +--- + +The purpose of this guide is to teach you how to write a high-quality definition file. +This guide is structured by showing documentation for some API, along with sample usage of that API, +and explaining how to write the corresponding declaration. + +These examples are ordered in approximately increasing order of complexity. + +## Objects with Properties + +_Documentation_ + +> The global variable `myLib` has a function `makeGreeting` for creating greetings, +> and a property `numberOfGreetings` indicating the number of greetings made so far. + +_Code_ + +```ts +let result = myLib.makeGreeting("hello, world"); +console.log("The computed greeting is:" + result); + +let count = myLib.numberOfGreetings; +``` + +_Declaration_ + +Use `declare namespace` to describe types or values accessed by dotted notation. + +```ts +declare namespace myLib { + function makeGreeting(s: string): string; + let numberOfGreetings: number; +} +``` + +## Overloaded Functions + +_Documentation_ + +The `getWidget` function accepts a number and returns a Widget, or accepts a string and returns a Widget array. + +_Code_ + +```ts +let x: Widget = getWidget(43); + +let arr: Widget[] = getWidget("all of them"); +``` + +_Declaration_ + +```ts +declare function getWidget(n: number): Widget; +declare function getWidget(s: string): Widget[]; +``` + +## Reusable Types (Interfaces) + +_Documentation_ + +> When specifying a greeting, you must pass a `GreetingSettings` object. +> This object has the following properties: +> +> 1 - greeting: Mandatory string +> +> 2 - duration: Optional length of time (in milliseconds) +> +> 3 - color: Optional string, e.g. '#ff00ff' + +_Code_ + +```ts +greet({ + greeting: "hello world", + duration: 4000 +}); +``` + +_Declaration_ + +Use an `interface` to define a type with properties. + +```ts +interface GreetingSettings { + greeting: string; + duration?: number; + color?: string; +} + +declare function greet(setting: GreetingSettings): void; +``` + +## Reusable Types (Type Aliases) + +_Documentation_ + +> Anywhere a greeting is expected, you can provide a `string`, a function returning a `string`, or a `Greeter` instance. + +_Code_ + +```ts +function getGreeting() { + return "howdy"; +} +class MyGreeter extends Greeter {} + +greet("hello"); +greet(getGreeting); +greet(new MyGreeter()); +``` + +_Declaration_ + +You can use a type alias to make a shorthand for a type: + +```ts +type GreetingLike = string | (() => string) | MyGreeter; + +declare function greet(g: GreetingLike): void; +``` + +## Organizing Types + +_Documentation_ + +> The `greeter` object can log to a file or display an alert. +> You can provide LogOptions to `.log(...)` and alert options to `.alert(...)` + +_Code_ + +```ts +const g = new Greeter("Hello"); +g.log({ verbose: true }); +g.alert({ modal: false, title: "Current Greeting" }); +``` + +_Declaration_ + +Use namespaces to organize types. + +```ts +declare namespace GreetingLib { + interface LogOptions { + verbose?: boolean; + } + interface AlertOptions { + modal: boolean; + title?: string; + color?: string; + } +} +``` + +You can also create nested namespaces in one declaration: + +```ts +declare namespace GreetingLib.Options { + // Refer to via GreetingLib.Options.Log + interface Log { + verbose?: boolean; + } + interface Alert { + modal: boolean; + title?: string; + color?: string; + } +} +``` + +## Classes + +_Documentation_ + +> You can create a greeter by instantiating the `Greeter` object, or create a customized greeter by extending from it. + +_Code_ + +```ts +const myGreeter = new Greeter("hello, world"); +myGreeter.greeting = "howdy"; +myGreeter.showGreeting(); + +class SpecialGreeter extends Greeter { + constructor() { + super("Very special greetings"); + } +} +``` + +_Declaration_ + +Use `declare class` to describe a class or class-like object. +Classes can have properties and methods as well as a constructor. + +```ts +declare class Greeter { + constructor(greeting: string); + + greeting: string; + showGreeting(): void; +} +``` + +## Global Variables + +_Documentation_ + +> The global variable `foo` contains the number of widgets present. + +_Code_ + +```ts +console.log("Half the number of widgets is " + foo / 2); +``` + +_Declaration_ + +Use `declare var` to declare variables. +If the variable is read-only, you can use `declare const`. +You can also use `declare let` if the variable is block-scoped. + +```ts +/** The number of widgets present */ +declare var foo: number; +``` + +## Global Functions + +_Documentation_ + +> You can call the function `greet` with a string to show a greeting to the user. + +_Code_ + +```ts +greet("hello, world"); +``` + +_Declaration_ + +Use `declare function` to declare functions. + +```ts +declare function greet(greeting: string): void; +``` + diff --git a/docs/documentation/zh/declaration-files/Consumption.md b/docs/documentation/zh/declaration-files/Consumption.md new file mode 100644 index 00000000..a68c03b2 --- /dev/null +++ b/docs/documentation/zh/declaration-files/Consumption.md @@ -0,0 +1,44 @@ +--- +title: Consumption +layout: docs +permalink: /docs/handbook/declaration-files/consumption.html +oneline: "How to download d.ts files for your project" +--- + +## Downloading + +Getting type declarations requires no tools apart from npm. + +As an example, getting the declarations for a library like lodash takes nothing more than the following command + +```cmd +npm install --save-dev @types/lodash +``` + +It is worth noting that if the npm package already includes its declaration file as described in [Publishing](/docs/handbook/declaration-files/publishing.html), downloading the corresponding `@types` package is not needed. + +## Consuming + +From there you’ll be able to use lodash in your TypeScript code with no fuss. +This works for both modules and global code. + +For example, once you’ve `npm install`-ed your type declarations, you can use imports and write + +```ts +import * as _ from "lodash"; +_.padStart("Hello TypeScript!", 20, " "); +``` + +or if you’re not using modules, you can just use the global variable `_`. + +```ts +_.padStart("Hello TypeScript!", 20, " "); +``` + +## Searching + +For the most part, type declaration packages should always have the same name as the package name on `npm`, but prefixed with `@types/`, +but if you need, you can check out [this Type Search](https://aka.ms/types) to find the package for your favorite library. + +> Note: if the declaration file you are searching for is not present, you can always contribute one back and help out the next developer looking for it. +> Please see the DefinitelyTyped [contribution guidelines page](http://definitelytyped.org/guides/contributing.html) for details. diff --git a/docs/documentation/zh/declaration-files/Deep Dive.md b/docs/documentation/zh/declaration-files/Deep Dive.md new file mode 100644 index 00000000..89950e96 --- /dev/null +++ b/docs/documentation/zh/declaration-files/Deep Dive.md @@ -0,0 +1,232 @@ +--- +title: Deep Dive +layout: docs +permalink: /docs/handbook/declaration-files/deep-dive.html +oneline: "How do d.ts files work, a deep dive" +--- + +## Declaration File Theory: A Deep Dive + +Structuring modules to give the exact API shape you want can be tricky. +For example, we might want a module that can be invoked with or without `new` to produce different types, +has a variety of named types exposed in a hierarchy, +and has some properties on the module object as well. + +By reading this guide, you'll have the tools to write complex declaration files that expose a friendly API surface. +This guide focuses on module (or UMD) libraries because the options here are more varied. + +## Key Concepts + +You can fully understand how to make any shape of declaration +by understanding some key concepts of how TypeScript works. + +### Types + +If you're reading this guide, you probably already roughly know what a type in TypeScript is. +To be more explicit, though, a _type_ is introduced with: + +- A type alias declaration (`type sn = number | string;`) +- An interface declaration (`interface I { x: number[]; }`) +- A class declaration (`class C { }`) +- An enum declaration (`enum E { A, B, C }`) +- An `import` declaration which refers to a type + +Each of these declaration forms creates a new type name. + +### Values + +As with types, you probably already understand what a value is. +Values are runtime names that we can reference in expressions. +For example `let x = 5;` creates a value called `x`. + +Again, being explicit, the following things create values: + +- `let`, `const`, and `var` declarations +- A `namespace` or `module` declaration which contains a value +- An `enum` declaration +- A `class` declaration +- An `import` declaration which refers to a value +- A `function` declaration + +### Namespaces + +Types can exist in _namespaces_. +For example, if we have the declaration `let x: A.B.C`, +we say that the type `C` comes from the `A.B` namespace. + +This distinction is subtle and important -- here, `A.B` is not necessarily a type or a value. + +## Simple Combinations: One name, multiple meanings + +Given a name `A`, we might find up to three different meanings for `A`: a type, a value or a namespace. +How the name is interpreted depends on the context in which it is used. +For example, in the declaration `let m: A.A = A;`, +`A` is used first as a namespace, then as a type name, then as a value. +These meanings might end up referring to entirely different declarations! + +This may seem confusing, but it's actually very convenient as long as we don't excessively overload things. +Let's look at some useful aspects of this combining behavior. + +### Built-in Combinations + +Astute readers will notice that, for example, `class` appeared in both the _type_ and _value_ lists. +The declaration `class C { }` creates two things: +a _type_ `C` which refers to the instance shape of the class, +and a _value_ `C` which refers to the constructor function of the class. +Enum declarations behave similarly. + +### User Combinations + +Let's say we wrote a module file `foo.d.ts`: + +```ts +export var SomeVar: { a: SomeType }; +export interface SomeType { + count: number; +} +``` + +Then consumed it: + +```ts +import * as foo from "./foo"; +let x: foo.SomeType = foo.SomeVar.a; +console.log(x.count); +``` + +This works well enough, but we might imagine that `SomeType` and `SomeVar` were very closely related +such that you'd like them to have the same name. +We can use combining to present these two different objects (the value and the type) under the same name `Bar`: + +```ts +export var Bar: { a: Bar }; +export interface Bar { + count: number; +} +``` + +This presents a very good opportunity for destructuring in the consuming code: + +```ts +import { Bar } from "./foo"; +let x: Bar = Bar.a; +console.log(x.count); +``` + +Again, we've used `Bar` as both a type and a value here. +Note that we didn't have to declare the `Bar` value as being of the `Bar` type -- they're independent. + +## Advanced Combinations + +Some kinds of declarations can be combined across multiple declarations. +For example, `class C { }` and `interface C { }` can co-exist and both contribute properties to the `C` types. + +This is legal as long as it does not create a conflict. +A general rule of thumb is that values always conflict with other values of the same name unless they are declared as `namespace`s, +types will conflict if they are declared with a type alias declaration (`type s = string`), +and namespaces never conflict. + +Let's see how this can be used. + +### Adding using an `interface` + +We can add additional members to an `interface` with another `interface` declaration: + +```ts +interface Foo { + x: number; +} +// ... elsewhere ... +interface Foo { + y: number; +} +let a: Foo = ...; +console.log(a.x + a.y); // OK +``` + +This also works with classes: + +```ts +class Foo { + x: number; +} +// ... elsewhere ... +interface Foo { + y: number; +} +let a: Foo = ...; +console.log(a.x + a.y); // OK +``` + +Note that we cannot add to type aliases (`type s = string;`) using an interface. + +### Adding using a `namespace` + +A `namespace` declaration can be used to add new types, values, and namespaces in any way which does not create a conflict. + +For example, we can add a static member to a class: + +```ts +class C {} +// ... elsewhere ... +namespace C { + export let x: number; +} +let y = C.x; // OK +``` + +Note that in this example, we added a value to the _static_ side of `C` (its constructor function). +This is because we added a _value_, and the container for all values is another value +(types are contained by namespaces, and namespaces are contained by other namespaces). + +We could also add a namespaced type to a class: + +```ts +class C {} +// ... elsewhere ... +namespace C { + export interface D {} +} +let y: C.D; // OK +``` + +In this example, there wasn't a namespace `C` until we wrote the `namespace` declaration for it. +The meaning `C` as a namespace doesn't conflict with the value or type meanings of `C` created by the class. + +Finally, we could perform many different merges using `namespace` declarations. +This isn't a particularly realistic example, but shows all sorts of interesting behavior: + +```ts +namespace X { + export interface Y {} + export class Z {} +} + +// ... elsewhere ... +namespace X { + export var Y: number; + export namespace Z { + export class C {} + } +} +type X = string; +``` + +In this example, the first block creates the following name meanings: + +- A value `X` (because the `namespace` declaration contains a value, `Z`) +- A namespace `X` (because the `namespace` declaration contains a type, `Y`) +- A type `Y` in the `X` namespace +- A type `Z` in the `X` namespace (the instance shape of the class) +- A value `Z` that is a property of the `X` value (the constructor function of the class) + +The second block creates the following name meanings: + +- A value `Y` (of type `number`) that is a property of the `X` value +- A namespace `Z` +- A value `Z` that is a property of the `X` value +- A type `C` in the `X.Z` namespace +- A value `C` that is a property of the `X.Z` value +- A type `X` + + diff --git a/docs/documentation/zh/declaration-files/Do's and Don'ts.md b/docs/documentation/zh/declaration-files/Do's and Don'ts.md new file mode 100644 index 00000000..34ddcbd8 --- /dev/null +++ b/docs/documentation/zh/declaration-files/Do's and Don'ts.md @@ -0,0 +1,241 @@ +--- +title: Do's and Don'ts +layout: docs +permalink: /docs/handbook/declaration-files/do-s-and-don-ts.html +oneline: "Recommendations for writing d.ts files" +--- + +## General Types + +## `Number`, `String`, `Boolean`, `Symbol` and `Object` + +❌ **Don't** ever use the types `Number`, `String`, `Boolean`, `Symbol`, or `Object` +These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code. + +```ts +/* WRONG */ +function reverse(s: String): String; +``` + +✅ **Do** use the types `number`, `string`, `boolean`, and `symbol`. + +```ts +/* OK */ +function reverse(s: string): string; +``` + +Instead of `Object`, use the non-primitive `object` type ([added in TypeScript 2.2](../release-notes/typescript-2-2.html#object-type)). + +## Generics + +❌ **Don't** ever have a generic type which doesn't use its type parameter. +See more details in [TypeScript FAQ page](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-type-inference-work-on-this-interface-interface-foot--). + +## any + +❌ **Don't** use `any` as a type unless you are in the process of migrating a JavaScript project to TypeScript. The compiler _effectively_ treats `any` as "please turn off type checking for this thing". It is similar to putting an `@ts-ignore` comment around every usage of the variable. This can be very helpful when you are first migrating a JavaScript project to TypeScript as you can set the type for stuff you haven't migrated yet as `any`, but in a full TypeScript project you are disabling type checking for any parts of your program that use it. + +In cases where you don't know what type you want to accept, or when you want to accept anything because you will be blindly passing it through without interacting with it, you can use [`unknown`](/play/#example/unknown-and-never). + + + +## Callback Types + +## Return Types of Callbacks + + + +❌ **Don't** use the return type `any` for callbacks whose value will be ignored: + +```ts +/* WRONG */ +function fn(x: () => any) { + x(); +} +``` + +✅ **Do** use the return type `void` for callbacks whose value will be ignored: + +```ts +/* OK */ +function fn(x: () => void) { + x(); +} +``` + +❔ **Why:** Using `void` is safer because it prevents you from accidentally using the return value of `x` in an unchecked way: + +```ts +function fn(x: () => void) { + var k = x(); // oops! meant to do something else + k.doSomething(); // error, but would be OK if the return type had been 'any' +} +``` + +## Optional Parameters in Callbacks + +❌ **Don't** use optional parameters in callbacks unless you really mean it: + +```ts +/* WRONG */ +interface Fetcher { + getObject(done: (data: any, elapsedTime?: number) => void): void; +} +``` + +This has a very specific meaning: the `done` callback might be invoked with 1 argument or might be invoked with 2 arguments. +The author probably intended to say that the callback might not care about the `elapsedTime` parameter, +but there's no need to make the parameter optional to accomplish this -- +it's always legal to provide a callback that accepts fewer arguments. + +✅ **Do** write callback parameters as non-optional: + +```ts +/* OK */ +interface Fetcher { + getObject(done: (data: any, elapsedTime: number) => void): void; +} +``` + +## Overloads and Callbacks + +❌ **Don't** write separate overloads that differ only on callback arity: + +```ts +/* WRONG */ +declare function beforeAll(action: () => void, timeout?: number): void; +declare function beforeAll( + action: (done: DoneFn) => void, + timeout?: number +): void; +``` + +✅ **Do** write a single overload using the maximum arity: + +```ts +/* OK */ +declare function beforeAll( + action: (done: DoneFn) => void, + timeout?: number +): void; +``` + +❔ **Why:** It's always legal for a callback to disregard a parameter, so there's no need for the shorter overload. +Providing a shorter callback first allows incorrectly-typed functions to be passed in because they match the first overload. + +## Function Overloads + +## Ordering + +❌ **Don't** put more general overloads before more specific overloads: + +```ts +/* WRONG */ +declare function fn(x: any): any; +declare function fn(x: HTMLElement): number; +declare function fn(x: HTMLDivElement): string; + +var myElem: HTMLDivElement; +var x = fn(myElem); // x: any, wat? +``` + +✅ **Do** sort overloads by putting the more general signatures after more specific signatures: + +```ts +/* OK */ +declare function fn(x: HTMLDivElement): string; +declare function fn(x: HTMLElement): number; +declare function fn(x: any): any; + +var myElem: HTMLDivElement; +var x = fn(myElem); // x: string, :) +``` + +❔ **Why:** TypeScript chooses the _first matching overload_ when resolving function calls. +When an earlier overload is "more general" than a later one, the later one is effectively hidden and cannot be called. + +## Use Optional Parameters + +❌ **Don't** write several overloads that differ only in trailing parameters: + +```ts +/* WRONG */ +interface Example { + diff(one: string): number; + diff(one: string, two: string): number; + diff(one: string, two: string, three: boolean): number; +} +``` + +✅ **Do** use optional parameters whenever possible: + +```ts +/* OK */ +interface Example { + diff(one: string, two?: string, three?: boolean): number; +} +``` + +Note that this collapsing should only occur when all overloads have the same return type. + +❔ **Why:** This is important for two reasons. + +TypeScript resolves signature compatibility by seeing if any signature of the target can be invoked with the arguments of the source, +_and extraneous arguments are allowed_. +This code, for example, exposes a bug only when the signature is correctly written using optional parameters: + +```ts +function fn(x: (a: string, b: number, c: number) => void) {} +var x: Example; +// When written with overloads, OK -- used first overload +// When written with optionals, correctly an error +fn(x.diff); +``` + +The second reason is when a consumer uses the "strict null checking" feature of TypeScript. +Because unspecified parameters appear as `undefined` in JavaScript, it's usually fine to pass an explicit `undefined` to a function with optional arguments. +This code, for example, should be OK under strict nulls: + +```ts +var x: Example; +// When written with overloads, incorrectly an error because of passing 'undefined' to 'string' +// When written with optionals, correctly OK +x.diff("something", true ? undefined : "hour"); +``` + +## Use Union Types + +❌ **Don't** write overloads that differ by type in only one argument position: + +```ts +/* WRONG */ +interface Moment { + utcOffset(): number; + utcOffset(b: number): Moment; + utcOffset(b: string): Moment; +} +``` + +✅ **Do** use union types whenever possible: + +```ts +/* OK */ +interface Moment { + utcOffset(): number; + utcOffset(b: number | string): Moment; +} +``` + +Note that we didn't make `b` optional here because the return types of the signatures differ. + +❔ **Why:** This is important for people who are "passing through" a value to your function: + +```ts +function fn(x: string): void; +function fn(x: number): void; +function fn(x: number | string) { + // When written with separate overloads, incorrectly an error + // When written with union types, correctly OK + return moment().utcOffset(x); +} +``` diff --git a/docs/documentation/zh/declaration-files/Introduction.md b/docs/documentation/zh/declaration-files/Introduction.md new file mode 100644 index 00000000..2b1c9603 --- /dev/null +++ b/docs/documentation/zh/declaration-files/Introduction.md @@ -0,0 +1,53 @@ +--- +title: Introduction +layout: docs +permalink: /docs/handbook/declaration-files/introduction.html +oneline: "How to write a high-quality TypeScript Declaration (d.ts) file" +--- + +The Declaration Files section is designed to teach you how to write a high-quality TypeScript Declaration File. We need to assume basic familiarity with the TypeScript language in order to get started. + +If you haven't already, you should read the [TypeScript Handbook](/docs/handbook/2/basic-types.html) +to familiarize yourself with basic concepts, especially types and modules. + +The most common case for learning how .d.ts files work is that you're typing an npm package with no types. +In that case, you can jump straight to [Modules .d.ts](/docs/handbook/declaration-files/templates/module-d-ts.html). + +The Declaration Files section is broken down into the following sections. + +## [Declaration Reference](/docs/handbook/declaration-files/by-example.html) + +We are often faced with writing a declaration file when we only have examples of the underlying library to guide us. +The [Declaration Reference](/docs/handbook/declaration-files/by-example.html) section shows many common API patterns and how to write declarations for each of them. +This guide is aimed at the TypeScript novice who may not yet be familiar with every language construct in TypeScript. + +## [Library Structures](/docs/handbook/declaration-files/library-structures.html) + +The [Library Structures](/docs/handbook/declaration-files/library-structures.html) guide helps you understand common library formats and how to write a proper declaration file for each format. +If you're editing an existing file, you probably don't need to read this section. +Authors of new declaration files are strongly encouraged to read this section to properly understand how the format of the library influences the writing of the declaration file. + +In the Template section you'll find a number of declaration files that serve as a useful starting point +when writing a new file. If you already know what your structure is, see the d.ts Template section in the sidebar. + +## [Do's and Don'ts](/docs/handbook/declaration-files/do-s-and-don-ts.html) + +Many common mistakes in declaration files can be easily avoided. +The [Do's and Don'ts](/docs/handbook/declaration-files/do-s-and-don-ts.html) section identifies common errors, +describes how to detect them, +and how to fix them. +Everyone should read this section to help themselves avoid common mistakes. + +## [Deep Dive](/docs/handbook/declaration-files/deep-dive.html) + +For seasoned authors interested in the underlying mechanics of how declaration files work, +the [Deep Dive](/docs/handbook/declaration-files/deep-dive.html) section explains many advanced concepts in declaration writing, +and shows how to leverage these concepts to create cleaner and more intuitive declaration files. + +## [Publish to npm](/docs/handbook/declaration-files/publishing.html) + +The [Publishing](/docs/handbook/declaration-files/publishing.html) section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages. + +## [Find and Install Declaration Files](/docs/handbook/declaration-files/consumption.html) + +For JavaScript library users, the [Consumption](/docs/handbook/declaration-files/consumption.html) section offers a few simple steps to locate and install corresponding declaration files. diff --git a/docs/documentation/zh/declaration-files/Library Structures.md b/docs/documentation/zh/declaration-files/Library Structures.md new file mode 100644 index 00000000..b2e57311 --- /dev/null +++ b/docs/documentation/zh/declaration-files/Library Structures.md @@ -0,0 +1,326 @@ +--- +title: Library Structures +layout: docs +permalink: /docs/handbook/declaration-files/library-structures.html +oneline: How to structure your d.ts files +--- + +Broadly speaking, the way you _structure_ your declaration file depends on how the library is consumed. +There are many ways of offering a library for consumption in JavaScript, and you'll need to write your declaration file to match it. +This guide covers how to identify common library patterns, and how to write declaration files which correspond to that pattern. + +Each type of major library structuring pattern has a corresponding file in the [Templates](/docs/handbook/declaration-files/templates.html) section. +You can start with these templates to help you get going faster. + +## Identifying Kinds of Libraries + +First, we'll review the kinds of libraries TypeScript declaration files can represent. +We'll briefly show how each kind of library is _used_, how it is _written_, and list some example libraries from the real world. + +Identifying the structure of a library is the first step in writing its declaration file. +We'll give hints on how to identify structure both based on its _usage_ and its _code_. +Depending on the library's documentation and organization, one might be easier than the other. +We recommend using whichever is more comfortable to you. + +## What should you look for? + +Question to ask yourself while looking at a library you are trying to type. + +1. How do you obtain the library? + + For example, can you _only_ get it through npm or only from a CDN? + +2. How would you import it? + + Does it add a global object? Does it use `require` or `import`/`export` statements? + +## Smaller samples for different types of libraries + +## Modular Libraries + +Almost every modern Node.js library falls into the module family. +These type of libraries only work in a JS environment with a module loader. +For example, `express` only works in Node.js and must be loaded using the CommonJS `require` function. + +ECMAScript 2015 (also known as ES2015, ECMAScript 6, and ES6), CommonJS, and RequireJS have similar notions of _importing_ a _module_. +In JavaScript CommonJS (Node.js), for example, you would write + +```js +var fs = require("fs"); +``` + +In TypeScript or ES6, the `import` keyword serves the same purpose: + +```ts +import * as fs from "fs"; +``` + +You'll typically see modular libraries include one of these lines in their documentation: + +```js +var someLib = require("someLib"); +``` + +or + +```js +define(..., ['someLib'], function(someLib) { + +}); +``` + +As with global modules, you might see these examples in the documentation of [a UMD](#umd) module, so be sure to check the code or documentation. + +### Identifying a Module Library from Code + +Modular libraries will typically have at least some of the following: + +- Unconditional calls to `require` or `define` +- Declarations like `import * as a from 'b';` or `export c;` +- Assignments to `exports` or `module.exports` + +They will rarely have: + +- Assignments to properties of `window` or `global` + +### Templates For Modules + +There are four templates available for modules, +[`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html), [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html), [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html) and [`module-plugin.d.ts`](/docs/handbook/declaration-files/templates/module-plugin-d-ts.html). + +You should first read [`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html) for an overview on the way they all work. + +Then use the template [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html) if your module can be _called_ like a function: + +```js +const x = require("foo"); +// Note: calling 'x' as a function +const y = x(42); +``` + +Use the template [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html) if your module can be _constructed_ using `new`: + +```js +const x = require("bar"); +// Note: using 'new' operator on the imported variable +const y = new x("hello"); +``` + +If you have a module which when imported, makes changes to other modules use template [`module-plugin.d.ts`](/docs/handbook/declaration-files/templates/module-plugin-d-ts.html): + +```js +const jest = require("jest"); +require("jest-matchers-files"); +``` + +## Global Libraries + +A _global_ library is one that can be accessed from the global scope (i.e. without using any form of `import`). +Many libraries simply expose one or more global variables for use. +For example, if you were using [jQuery](https://jquery.com/), the `$` variable can be used by simply referring to it: + +```ts +$(() => { + console.log("hello!"); +}); +``` + +You'll usually see guidance in the documentation of a global library of how to use the library in an HTML script tag: + +```html + +``` + +Today, most popular globally-accessible libraries are actually written as UMD libraries (see below). +UMD library documentation is hard to distinguish from global library documentation. +Before writing a global declaration file, make sure the library isn't actually UMD. + +### Identifying a Global Library from Code + +Global library code is usually extremely simple. +A global "Hello, world" library might look like this: + +```js +function createGreeting(s) { + return "Hello, " + s; +} +``` + +or like this: + +```js +// Web +window.createGreeting = function (s) { + return "Hello, " + s; +}; + +// Node +global.createGreeting = function (s) { + return "Hello, " + s; +}; + +// Potentially any runtime +globalThis.createGreeting = function (s) { + return "Hello, " + s; +}; +``` + +When looking at the code of a global library, you'll usually see: + +- Top-level `var` statements or `function` declarations +- One or more assignments to `window.someName` +- Assumptions that DOM primitives like `document` or `window` exist + +You _won't_ see: + +- Checks for, or usage of, module loaders like `require` or `define` +- CommonJS/Node.js-style imports of the form `var fs = require("fs");` +- Calls to `define(...)` +- Documentation describing how to `require` or import the library + +### Examples of Global Libraries + +Because it's usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style. +However, libraries that are small and require the DOM (or have _no_ dependencies) may still be global. + +### Global Library Template + +The template file [`global.d.ts`](/docs/handbook/declaration-files/templates/global-plugin-d-ts.html) defines an example library `myLib`. +Be sure to read the ["Preventing Name Conflicts" footnote](#preventing-name-conflicts). + +## _UMD_ + +A _UMD_ module is one that can _either_ be used as module (through an import), or as a global (when run in an environment without a module loader). +Many popular libraries, such as [Moment.js](http://momentjs.com/), are written this way. +For example, in Node.js or using RequireJS, you would write: + +```ts +import moment = require("moment"); +console.log(moment.format()); +``` + +whereas in a vanilla browser environment you would write: + +```js +console.log(moment.format()); +``` + +### Identifying a UMD library + +[UMD modules](https://github.com/umdjs/umd) check for the existence of a module loader environment. +This is an easy-to-spot pattern that looks something like this: + +```js +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["libName"], factory); + } else if (typeof module === "object" && module.exports) { + module.exports = factory(require("libName")); + } else { + root.returnExports = factory(root.libName); + } +}(this, function (b) { +``` + +If you see tests for `typeof define`, `typeof window`, or `typeof module` in the code of a library, especially at the top of the file, it's almost always a UMD library. + +Documentation for UMD libraries will also often demonstrate a "Using in Node.js" example showing `require`, +and a "Using in the browser" example showing using a ` +``` + +Today, most popular globally-accessible libraries are actually written as UMD libraries (see below). +UMD library documentation is hard to distinguish from global library documentation. +Before writing a global declaration file, make sure the library isn't actually UMD. + +## Identifying a Global Library from Code + +Global library code is usually extremely simple. +A global "Hello, world" library might look like this: + +```js +function createGreeting(s) { + return "Hello, " + s; +} +``` + +or like this: + +```js +window.createGreeting = function (s) { + return "Hello, " + s; +}; +``` + +When looking at the code of a global library, you'll usually see: + +- Top-level `var` statements or `function` declarations +- One or more assignments to `window.someName` +- Assumptions that DOM primitives like `document` or `window` exist + +You _won't_ see: + +- Checks for, or usage of, module loaders like `require` or `define` +- CommonJS/Node.js-style imports of the form `var fs = require("fs");` +- Calls to `define(...)` +- Documentation describing how to `require` or import the library + +## Examples of Global Libraries + +Because it's usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style. +However, libraries that are small and require the DOM (or have _no_ dependencies) may still be global. + +## Global Library Template + +You can see an example DTS below: + +```ts +// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] +// Project: [~THE PROJECT NAME~] +// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> + +/*~ If this library is callable (e.g. can be invoked as myLib(3)), + *~ include those call signatures here. + *~ Otherwise, delete this section. + */ +declare function myLib(a: string): string; +declare function myLib(a: number): number; + +/*~ If you want the name of this library to be a valid type name, + *~ you can do so here. + *~ + *~ For example, this allows us to write 'var x: myLib'; + *~ Be sure this actually makes sense! If it doesn't, just + *~ delete this declaration and add types inside the namespace below. + */ +interface myLib { + name: string; + length: number; + extras?: string[]; +} + +/*~ If your library has properties exposed on a global variable, + *~ place them here. + *~ You should also place types (interfaces and type alias) here. + */ +declare namespace myLib { + //~ We can write 'myLib.timeout = 50;' + let timeout: number; + + //~ We can access 'myLib.version', but not change it + const version: string; + + //~ There's some class we can create via 'let c = new myLib.Cat(42)' + //~ Or reference e.g. 'function f(c: myLib.Cat) { ... } + class Cat { + constructor(n: number); + + //~ We can read 'c.age' from a 'Cat' instance + readonly age: number; + + //~ We can invoke 'c.purr()' from a 'Cat' instance + purr(): void; + } + + //~ We can declare a variable as + //~ 'var s: myLib.CatSettings = { weight: 5, name: "Maru" };' + interface CatSettings { + weight: number; + name: string; + tailLength?: number; + } + + //~ We can write 'const v: myLib.VetID = 42;' + //~ or 'const v: myLib.VetID = "bob";' + type VetID = string | number; + + //~ We can invoke 'myLib.checkCat(c)' or 'myLib.checkCat(c, v);' + function checkCat(c: Cat, s?: VetID); +} +``` diff --git a/docs/documentation/zh/declaration-files/templates/module-class.d.ts.md b/docs/documentation/zh/declaration-files/templates/module-class.d.ts.md new file mode 100644 index 00000000..4825b594 --- /dev/null +++ b/docs/documentation/zh/declaration-files/templates/module-class.d.ts.md @@ -0,0 +1,83 @@ +--- +title: "Module: Class" +layout: docs +permalink: /docs/handbook/declaration-files/templates/module-class-d-ts.html +--- + + + +For example, when you want to work with JavaScript code which looks like: + +```ts +const Greeter = require("super-greeter"); + +const greeter = new Greeter(); +greeter.greet(); +``` + +To handle both importing via UMD and modules: + +```ts +// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] +// Project: [~THE PROJECT NAME~] +// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> + +/*~ This is the module template file for class modules. + *~ You should rename it to index.d.ts and place it in a folder with the same name as the module. + *~ For example, if you were writing a file for "super-greeter", this + *~ file should be 'super-greeter/index.d.ts' + */ + +// Note that ES6 modules cannot directly export class objects. +// This file should be imported using the CommonJS-style: +// import x = require('[~THE MODULE~]'); +// +// Alternatively, if --allowSyntheticDefaultImports or +// --esModuleInterop is turned on, this file can also be +// imported as a default import: +// import x from '[~THE MODULE~]'; +// +// Refer to the TypeScript documentation at +// https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require +// to understand common workarounds for this limitation of ES6 modules. + +/*~ If this module is a UMD module that exposes a global variable 'myClassLib' when + *~ loaded outside a module loader environment, declare that global here. + *~ Otherwise, delete this declaration. + */ +export as namespace "super-greeter"; + +/*~ This declaration specifies that the class constructor function + *~ is the exported object from the file + */ +export = Greeter; + +/*~ Write your module's methods and properties in this class */ +declare class Greeter { + constructor(customGreeting?: string); + + greet: void; + + myMethod(opts: MyClass.MyClassMethodOptions): number; +} + +/*~ If you want to expose types from your module as well, you can + *~ place them in this block. + *~ + *~ Note that if you decide to include this namespace, the module can be + *~ incorrectly imported as a namespace object, unless + *~ --esModuleInterop is turned on: + *~ import * as x from '[~THE MODULE~]'; // WRONG! DO NOT DO THIS! + */ +declare namespace MyClass { + export interface MyClassMethodOptions { + width?: number; + height?: number; + } +} +``` diff --git a/docs/documentation/zh/declaration-files/templates/module-function.d.ts.md b/docs/documentation/zh/declaration-files/templates/module-function.d.ts.md new file mode 100644 index 00000000..fde9ddf6 --- /dev/null +++ b/docs/documentation/zh/declaration-files/templates/module-function.d.ts.md @@ -0,0 +1,85 @@ +--- +title: "Module: Function" +layout: docs +permalink: /docs/handbook/declaration-files/templates/module-function-d-ts.html +--- + +For example, when you want to work with JavaScript code which looks like: + +```ts +import greeter from "super-greeter"; + +greeter(2); +greeter("Hello world"); +``` + +To handle both importing via UMD and modules: + +```ts +// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] +// Project: [~THE PROJECT NAME~] +// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> + +/*~ This is the module template file for function modules. + *~ You should rename it to index.d.ts and place it in a folder with the same name as the module. + *~ For example, if you were writing a file for "super-greeter", this + *~ file should be 'super-greeter/index.d.ts' + */ + +// Note that ES6 modules cannot directly export class objects. +// This file should be imported using the CommonJS-style: +// import x = require('[~THE MODULE~]'); +// +// Alternatively, if --allowSyntheticDefaultImports or +// --esModuleInterop is turned on, this file can also be +// imported as a default import: +// import x from '[~THE MODULE~]'; +// +// Refer to the TypeScript documentation at +// https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require +// to understand common workarounds for this limitation of ES6 modules. + +/*~ If this module is a UMD module that exposes a global variable 'myFuncLib' when + *~ loaded outside a module loader environment, declare that global here. + *~ Otherwise, delete this declaration. + */ +export as namespace myFuncLib; + +/*~ This declaration specifies that the function + *~ is the exported object from the file + */ +export = Greeter; + +/*~ This example shows how to have multiple overloads for your function */ +declare function Greeter(name: string): Greeter.NamedReturnType; +declare function Greeter(length: number): Greeter.LengthReturnType; + +/*~ If you want to expose types from your module as well, you can + *~ place them in this block. Often you will want to describe the + *~ shape of the return type of the function; that type should + *~ be declared in here, as this example shows. + *~ + *~ Note that if you decide to include this namespace, the module can be + *~ incorrectly imported as a namespace object, unless + *~ --esModuleInterop is turned on: + *~ import * as x from '[~THE MODULE~]'; // WRONG! DO NOT DO THIS! + */ +declare namespace Greeter { + export interface LengthReturnType { + width: number; + height: number; + } + export interface NamedReturnType { + firstName: string; + lastName: string; + } + + /*~ If the module also has properties, declare them here. For example, + *~ this declaration says that this code is legal: + *~ import f = require('super-greeter'); + *~ console.log(f.defaultName); + */ + export const defaultName: string; + export let defaultLength: number; +} +``` diff --git a/docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md b/docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md new file mode 100644 index 00000000..c150521f --- /dev/null +++ b/docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md @@ -0,0 +1,67 @@ +--- +title: "Module: Plugin" +layout: docs +permalink: /docs/handbook/declaration-files/templates/module-plugin-d-ts.html +--- + +For example, when you want to work with JavaScript code which extends another library. + +```ts +import { greeter } from "super-greeter"; + +// Normal Greeter API +greeter(2); +greeter("Hello world"); + +// Now we extend the object with a new function at runtime +import "hyper-super-greeter"; +greeter.hyperGreet(); +``` + +The definition for "super-greeter": + +```ts +/*~ This example shows how to have multiple overloads for your function */ +export interface GreeterFunction { + (name: string): void + (time: number): void +} + +/*~ This example shows how to export a function specified by an interface */ +export const greeter: GreeterFunction; +``` + +We can extend the existing module like the following: + +```ts +// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] +// Project: [~THE PROJECT NAME~] +// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> + +/*~ This is the module plugin template file. You should rename it to index.d.ts + *~ and place it in a folder with the same name as the module. + *~ For example, if you were writing a file for "super-greeter", this + *~ file should be 'super-greeter/index.d.ts' + */ + +/*~ On this line, import the module which this module adds to */ +import { greeter } from "super-greeter"; + +/*~ Here, declare the same module as the one you imported above + *~ then we expand the existing declaration of the greeter function + */ +export module "super-greeter" { + export interface GreeterFunction { + /** Greets even better! */ + hyperGreet(): void; + } +} +``` + +This uses [declaration merging](/docs/handbook/declaration-merging.html) + +## The Impact of ES6 on Module Plugins + +Some plugins add or modify top-level exports on existing modules. +While this is legal in CommonJS and other loaders, ES6 modules are considered immutable and this pattern will not be possible. +Because TypeScript is loader-agnostic, there is no compile-time enforcement of this policy, but developers intending to transition to an ES6 module loader should be aware of this. diff --git a/docs/documentation/zh/declaration-files/templates/module.d.ts.md b/docs/documentation/zh/declaration-files/templates/module.d.ts.md new file mode 100644 index 00000000..aa83daf1 --- /dev/null +++ b/docs/documentation/zh/declaration-files/templates/module.d.ts.md @@ -0,0 +1,311 @@ +--- +title: Modules .d.ts +layout: docs +permalink: /docs/handbook/declaration-files/templates/module-d-ts.html +--- + +## Comparing JavaScript to an example DTS + +## Common CommonJS Patterns + +A module using CommonJS patterns uses `module.exports` to describe the exported values. For example, here is a module which exports a function and a numerical constant: + +```js +const maxInterval = 12; + +function getArrayLength(arr) { + return arr.length; +} + +module.exports = { + getArrayLength, + maxInterval, +}; +``` + +This can be described by the following `.d.ts`: + +```ts +export function getArrayLength(arr: any[]): number; +export const maxInterval: 12; +``` + +The TypeScript playground can show you the `.d.ts` equivalent for JavaScript code. You can [try it yourself here](/play?useJavaScript=true#code/GYVwdgxgLglg9mABAcwKZQIICcsEMCeAMqmMlABYAUuOAlIgN6IBQiiW6IWSNWAdABsSZcswC+zCAgDOURAFtcADwAq5GKUQBeRAEYATM2by4AExBC+qJQAc4WKNO2NWKdNjxFhFADSvFquqk4sxAA). + +The `.d.ts` syntax intentionally looks like [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) syntax. +ES Modules was ratified by TC39 in 2019, while it has been available via transpilers for a long time, however if you have a JavaScript codebase using ES Modules: + +```js +export function getArrayLength(arr) { + return arr.length; +} +``` + +This would have the following `.d.ts` equivalent: + +```ts +export function getArrayLength(arr: any[]): number; +``` + +### Default Exports + +In CommonJS you can export any value as the default export, for example here is a regular expression module: + +```js +module.exports = /hello( world)?/; +``` + +Which can be described by the following .d.ts: + +```ts +declare const helloWorld: RegExp; +export default helloWorld; +``` + +Or a number: + +```js +module.exports = 3.142; +``` + +```ts +declare const pi: number; +export default pi; +``` + +One style of exporting in CommonJS is to export a function. +Because a function is also an object, then extra fields can be added and are included in the export. + +```js +function getArrayLength(arr) { + return arr.length; +} +getArrayLength.maxInterval = 12; + +module.exports = getArrayLength; +``` + +Which can be described with: + +```ts +export default function getArrayLength(arr: any[]): number; +export const maxInterval: 12; +``` + +Note that using `export default` in your .d.ts files requires [`esModuleInterop: true`](/tsconfig#esModuleInterop) to work. +If you can't have `esModuleInterop: true` in your project, such as when you're submitting a PR to Definitely Typed, you'll have to use the `export=` syntax instead. This older syntax is harder to use but works everywhere. +Here's how the above example would have to be written using `export=`: + +```ts +declare function getArrayLength(arr: any[]): number; +declare namespace getArrayLength { + declare const maxInterval: 12; +} + +export = getArrayLength; +``` + +See [Module: Functions](/docs/handbook/declaration-files/templates/module-function-d-ts.html) for details of how that works, and the [Modules reference](/docs/handbook/modules.html) page. + +## Handling Many Consuming Import + +There are many ways to import a module in modern consuming code: + +```ts +const fastify = require("fastify"); +const { fastify } = require("fastify"); +import fastify = require("fastify"); +import * as Fastify from "fastify"; +import { fastify, FastifyInstance } from "fastify"; +import fastify from "fastify"; +import fastify, { FastifyInstance } from "fastify"; +``` + +Covering all of these cases requires the JavaScript code to actually support all of these patterns. +To support many of these patterns, a CommonJS module would need to look something like: + +```js +class FastifyInstance {} + +function fastify() { + return new FastifyInstance(); +} + +fastify.FastifyInstance = FastifyInstance; + +// Allows for { fastify } +fastify.fastify = fastify; +// Allows for strict ES Module support +fastify.default = fastify; +// Sets the default export +module.exports = fastify; +``` + +## Types in Modules + +You may want to provide a type for JavaScript code which does not exist + +```js +function getArrayMetadata(arr) { + return { + length: getArrayLength(arr), + firstObject: arr[0], + }; +} + +module.exports = { + getArrayMetadata, +}; +``` + +This can be described with: + +```ts +export type ArrayMetadata = { + length: number; + firstObject: any | undefined; +}; +export function getArrayMetadata(arr: any[]): ArrayMetadata; +``` + +This example is a good case for [using generics](/docs/handbook/generics.html#generic-types) to provide richer type information: + +```ts +export type ArrayMetadata = { + length: number; + firstObject: ArrType | undefined; +}; + +export function getArrayMetadata( + arr: ArrType[] +): ArrayMetadata; +``` + +Now the type of the array propagates into the `ArrayMetadata` type. + +The types which are exported can then be re-used by consumers of the modules using either `import` or `import type` in TypeScript code or [JSDoc imports](/docs/handbook/jsdoc-supported-types.html#import-types). + +### Namespaces in Module Code + +Trying to describe the runtime relationship of JavaScript code can be tricky. +When the ES Module-like syntax doesn't provide enough tools to describe the exports then you can use `namespaces`. + +For example, you may have complex enough types to describe that you choose to namespace them inside your `.d.ts`: + +```ts +// This represents the JavaScript class which would be available at runtime +export class API { + constructor(baseURL: string); + getInfo(opts: API.InfoRequest): API.InfoResponse; +} + +// This namespace is merged with the API class and allows for consumers, and this file +// to have types which are nested away in their own sections. +declare namespace API { + export interface InfoRequest { + id: string; + } + + export interface InfoResponse { + width: number; + height: number; + } +} +``` + +To understand how namespaces work in `.d.ts` files read the [`.d.ts` deep dive](/docs/handbook/declaration-files/deep-dive.html). + +### Optional Global Usage + +You can use `export as namespace` to declare that your module will be available in the global scope in UMD contexts: + +```ts +export as namespace moduleName; +``` + +## Reference Example + +To give you an idea of how all these pieces can come together, here is a reference `.d.ts` to start with when making a new module + +```ts +// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] +// Project: [~THE PROJECT NAME~] +// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]> + +/*~ This is the module template file. You should rename it to index.d.ts + *~ and place it in a folder with the same name as the module. + *~ For example, if you were writing a file for "super-greeter", this + *~ file should be 'super-greeter/index.d.ts' + */ + +/*~ If this module is a UMD module that exposes a global variable 'myLib' when + *~ loaded outside a module loader environment, declare that global here. + *~ Otherwise, delete this declaration. + */ +export as namespace myLib; + +/*~ If this module exports functions, declare them like so. + */ +export function myFunction(a: string): string; +export function myOtherFunction(a: number): number; + +/*~ You can declare types that are available via importing the module */ +export interface SomeType { + name: string; + length: number; + extras?: string[]; +} + +/*~ You can declare properties of the module using const, let, or var */ +export const myField: number; +``` + +### Library file layout + +The layout of your declaration files should mirror the layout of the library. + +A library can consist of multiple modules, such as + +``` +myLib + +---- index.js + +---- foo.js + +---- bar + +---- index.js + +---- baz.js +``` + +These could be imported as + +```js +var a = require("myLib"); +var b = require("myLib/foo"); +var c = require("myLib/bar"); +var d = require("myLib/bar/baz"); +``` + +Your declaration files should thus be + +``` +@types/myLib + +---- index.d.ts + +---- foo.d.ts + +---- bar + +---- index.d.ts + +---- baz.d.ts +``` + +### Testing your types + +If you are planning on submitting these changes to DefinitelyTyped for everyone to also use, then we recommend you: + +> 1. Create a new folder in `node_modules/@types/[libname]` +> 2. Create an `index.d.ts` in that folder, and copy the example in +> 3. See where your usage of the module breaks, and start to fill out the index.d.ts +> 4. When you're happy, clone [DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped) and follow the instructions in the README. + +Otherwise + +> 1. Create a new file in the root of your source tree: `[libname].d.ts` +> 2. Add `declare module "[libname]" { }` +> 3. Add the template inside the braces of the declare module, and see where your usage breaks diff --git a/docs/documentation/zh/get-started/TS for Functional Programmers.md b/docs/documentation/zh/get-started/TS for Functional Programmers.md new file mode 100644 index 00000000..1721a141 --- /dev/null +++ b/docs/documentation/zh/get-started/TS for Functional Programmers.md @@ -0,0 +1,597 @@ +--- +title: TypeScript for Functional Programmers +short: TS for Functional Programmers +layout: docs +permalink: /docs/handbook/typescript-in-5-minutes-func.html +oneline: Learn TypeScript if you have a background in functional programming +--- + +TypeScript began its life as an attempt to bring traditional object-oriented types +to JavaScript so that the programmers at Microsoft could bring +traditional object-oriented programs to the web. As it has developed, TypeScript's type +system has evolved to model code written by native JavaScripters. The +resulting system is powerful, interesting and messy. + +This introduction is designed for working Haskell or ML programmers +who want to learn TypeScript. It describes how the type system of +TypeScript differs from Haskell's type system. It also describes +unique features of TypeScript's type system that arise from its +modelling of JavaScript code. + +This introduction does not cover object-oriented programming. In +practice, object-oriented programs in TypeScript are similar to those +in other popular languages with OO features. + +## Prerequisites + +In this introduction, I assume you know the following: + +- How to program in JavaScript, the good parts. +- Type syntax of a C-descended language. + +If you need to learn the good parts of JavaScript, read +[JavaScript: The Good Parts](http://shop.oreilly.com/product/9780596517748.do). +You may be able to skip the book if you know how to write programs in +a call-by-value lexically scoped language with lots of mutability and +not much else. +[R4RS Scheme](https://people.csail.mit.edu/jaffer/r4rs.pdf) is a good example. + +[The C++ Programming Language](http://www.stroustrup.com/4th.html) is +a good place to learn about C-style type syntax. Unlike C++, +TypeScript uses postfix types, like so: `x: string` instead of `string x`. + +## Concepts not in Haskell + +## Built-in types + +JavaScript defines 8 built-in types: + +| Type | Explanation | +| ----------- | ------------------------------------------- | +| `Number` | a double-precision IEEE 754 floating point. | +| `String` | an immutable UTF-16 string. | +| `BigInt` | integers in the arbitrary precision format. | +| `Boolean` | `true` and `false`. | +| `Symbol` | a unique value usually used as a key. | +| `Null` | equivalent to the unit type. | +| `Undefined` | also equivalent to the unit type. | +| `Object` | similar to records. | + +[See the MDN page for more detail](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures). + +TypeScript has corresponding primitive types for the built-in types: + +- `number` +- `string` +- `bigint` +- `boolean` +- `symbol` +- `null` +- `undefined` +- `object` + +### Other important TypeScript types + +| Type | Explanation | +| -------------- | ----------------------------------------------------------- | +| `unknown` | the top type. | +| `never` | the bottom type. | +| object literal | eg `{ property: Type }` | +| `void` | a subtype of `undefined` intended for use as a return type. | +| `T[]` | mutable arrays, also written `Array` | +| `[T, T]` | tuples, which are fixed-length but mutable | +| `(t: T) => U` | functions | + +Notes: + +1. Function syntax includes parameter names. This is pretty hard to get used to! + + ```ts + let fst: (a: any, b: any) => any = (a, b) => a; + + // or more precisely: + + let fst: (a: T, b: U) => T = (a, b) => a; + ``` + +2. Object literal type syntax closely mirrors object literal value syntax: + + ```ts + let o: { n: number; xs: object[] } = { n: 1, xs: [] }; + ``` + +3. `[T, T]` is a subtype of `T[]`. This is different than Haskell, where tuples are not related to lists. + +### Boxed types + +JavaScript has boxed equivalents of primitive types that contain the +methods that programmers associate with those types. TypeScript +reflects this with, for example, the difference between the primitive +type `number` and the boxed type `Number`. The boxed types are rarely +needed, since their methods return primitives. + +```ts +(1).toExponential(); +// equivalent to +Number.prototype.toExponential.call(1); +``` + +Note that calling a method on a numeric literal requires it to be in +parentheses to aid the parser. + +## Gradual typing + +TypeScript uses the type `any` whenever it can't tell what the type of +an expression should be. Compared to `Dynamic`, calling `any` a type +is an overstatement. It just turns off the type checker +wherever it appears. For example, you can push any value into an +`any[]` without marking the value in any way: + +```ts twoslash +// with "noImplicitAny": false in tsconfig.json, anys: any[] +const anys = []; +anys.push(1); +anys.push("oh no"); +anys.push({ anything: "goes" }); +``` + +And you can use an expression of type `any` anywhere: + +```ts +anys.map(anys[1]); // oh no, "oh no" is not a function +``` + +`any` is contagious, too — if you initialise a variable with an +expression of type `any`, the variable has type `any` too. + +```ts +let sepsis = anys[0] + anys[1]; // this could mean anything +``` + +To get an error when TypeScript produces an `any`, use +`"noImplicitAny": true`, or `"strict": true` in `tsconfig.json`. + +## Structural typing + +Structural typing is a familiar concept to most functional +programmers, although Haskell and most MLs are not +structurally typed. Its basic form is pretty simple: + +```ts +// @strict: false +let o = { x: "hi", extra: 1 }; // ok +let o2: { x: string } = o; // ok +``` + +Here, the object literal `{ x: "hi", extra: 1 }` has a matching +literal type `{ x: string, extra: number }`. That +type is assignable to `{ x: string }` since +it has all the required properties and those properties have +assignable types. The extra property doesn't prevent assignment, it +just makes it a subtype of `{ x: string }`. + +Named types just give a name to a type; for assignability purposes +there's no difference between the type alias `One` and the interface +type `Two` below. They both have a property `p: string`. (Type aliases +behave differently from interfaces with respect to recursive +definitions and type parameters, however.) + +```ts twoslash +// @errors: 2322 +type One = { p: string }; +interface Two { + p: string; +} +class Three { + p = "Hello"; +} + +let x: One = { p: "hi" }; +let two: Two = x; +two = new Three(); +``` + +## Unions + +In TypeScript, union types are untagged. In other words, they are not +discriminated unions like `data` in Haskell. However, you can often +discriminate types in a union using built-in tags or other properties. + +```ts twoslash +function start( + arg: string | string[] | (() => string) | { s: string } +): string { + // this is super common in JavaScript + if (typeof arg === "string") { + return commonCase(arg); + } else if (Array.isArray(arg)) { + return arg.map(commonCase).join(","); + } else if (typeof arg === "function") { + return commonCase(arg()); + } else { + return commonCase(arg.s); + } + + function commonCase(s: string): string { + // finally, just convert a string to another string + return s; + } +} +``` + +`string`, `Array` and `Function` have built-in type predicates, +conveniently leaving the object type for the `else` branch. It is +possible, however, to generate unions that are difficult to +differentiate at runtime. For new code, it's best to build only +discriminated unions. + +The following types have built-in predicates: + +| Type | Predicate | +| --------- | ---------------------------------- | +| string | `typeof s === "string"` | +| number | `typeof n === "number"` | +| bigint | `typeof m === "bigint"` | +| boolean | `typeof b === "boolean"` | +| symbol | `typeof g === "symbol"` | +| undefined | `typeof undefined === "undefined"` | +| function | `typeof f === "function"` | +| array | `Array.isArray(a)` | +| object | `typeof o === "object"` | + +Note that functions and arrays are objects at runtime, but have their +own predicates. + +### Intersections + +In addition to unions, TypeScript also has intersections: + +```ts twoslash +type Combined = { a: number } & { b: string }; +type Conflicting = { a: number } & { a: string }; +``` + +`Combined` has two properties, `a` and `b`, just as if they had been +written as one object literal type. Intersection and union are +recursive in case of conflicts, so `Conflicting.a: number & string`. + +## Unit types + +Unit types are subtypes of primitive types that contain exactly one +primitive value. For example, the string `"foo"` has the type +`"foo"`. Since JavaScript has no built-in enums, it is common to use a set of +well-known strings instead. Unions of string literal types allow +TypeScript to type this pattern: + +```ts twoslash +declare function pad(s: string, n: number, direction: "left" | "right"): string; +pad("hi", 10, "left"); +``` + +When needed, the compiler _widens_ — converts to a +supertype — the unit type to the primitive type, such as `"foo"` +to `string`. This happens when using mutability, which can hamper some +uses of mutable variables: + +```ts twoslash +// @errors: 2345 +declare function pad(s: string, n: number, direction: "left" | "right"): string; +// ---cut--- +let s = "right"; +pad("hi", 10, s); // error: 'string' is not assignable to '"left" | "right"' +``` + +Here's how the error happens: + +- `"right": "right"` +- `s: string` because `"right"` widens to `string` on assignment to a mutable variable. +- `string` is not assignable to `"left" | "right"` + +You can work around this with a type annotation for `s`, but that +in turn prevents assignments to `s` of variables that are not of type +`"left" | "right"`. + +```ts twoslash +declare function pad(s: string, n: number, direction: "left" | "right"): string; +// ---cut--- +let s: "left" | "right" = "right"; +pad("hi", 10, s); +``` + +## Concepts similar to Haskell + +## Contextual typing + +TypeScript has some obvious places where it can infer types, like +variable declarations: + +```ts twoslash +let s = "I'm a string!"; +``` + +But it also infers types in a few other places that you may not expect +if you've worked with other C-syntax languages: + +```ts twoslash +declare function map(f: (t: T) => U, ts: T[]): U[]; +let sns = map((n) => n.toString(), [1, 2, 3]); +``` + +Here, `n: number` in this example also, despite the fact that `T` and `U` +have not been inferred before the call. In fact, after `[1,2,3]` has +been used to infer `T=number`, the return type of `n => n.toString()` +is used to infer `U=string`, causing `sns` to have the type +`string[]`. + +Note that inference will work in any order, but intellisense will only +work left-to-right, so TypeScript prefers to declare `map` with the +array first: + +```ts twoslash +declare function map(ts: T[], f: (t: T) => U): U[]; +``` + +Contextual typing also works recursively through object literals, and +on unit types that would otherwise be inferred as `string` or +`number`. And it can infer return types from context: + +```ts twoslash +declare function run(thunk: (t: T) => void): T; +let i: { inference: string } = run((o) => { + o.inference = "INSERT STATE HERE"; +}); +``` + +The type of `o` is determined to be `{ inference: string }` because + +1. Declaration initialisers are contextually typed by the + declaration's type: `{ inference: string }`. +2. The return type of a call uses the contextual type for inferences, + so the compiler infers that `T={ inference: string }`. +3. Arrow functions use the contextual type to type their parameters, + so the compiler gives `o: { inference: string }`. + +And it does so while you are typing, so that after typing `o.`, you +get completions for the property `inference`, along with any other +properties you'd have in a real program. +Altogether, this feature can make TypeScript's inference look a bit +like a unifying type inference engine, but it is not. + +## Type aliases + +Type aliases are mere aliases, just like `type` in Haskell. The +compiler will attempt to use the alias name wherever it was used in +the source code, but does not always succeed. + +```ts twoslash +type Size = [number, number]; +let x: Size = [101.1, 999.9]; +``` + +The closest equivalent to `newtype` is a _tagged intersection_: + +```ts +type FString = string & { __compileTimeOnly: any }; +``` + +An `FString` is just like a normal string, except that the compiler +thinks it has a property named `__compileTimeOnly` that doesn't +actually exist. This means that `FString` can still be assigned to +`string`, but not the other way round. + +## Discriminated Unions + +The closest equivalent to `data` is a union of types with discriminant +properties, normally called discriminated unions in TypeScript: + +```ts +type Shape = + | { kind: "circle"; radius: number } + | { kind: "square"; x: number } + | { kind: "triangle"; x: number; y: number }; +``` + +Unlike Haskell, the tag, or discriminant, is just a property in each +object type. Each variant has an identical property with a different +unit type. This is still a normal union type; the leading `|` is +an optional part of the union type syntax. You can discriminate the +members of the union using normal JavaScript code: + +```ts twoslash +type Shape = + | { kind: "circle"; radius: number } + | { kind: "square"; x: number } + | { kind: "triangle"; x: number; y: number }; + +function area(s: Shape) { + if (s.kind === "circle") { + return Math.PI * s.radius * s.radius; + } else if (s.kind === "square") { + return s.x * s.x; + } else { + return (s.x * s.y) / 2; + } +} +``` + +Note that the return type of `area` is inferred to be `number` because +TypeScript knows the function is total. If some variant is not +covered, the return type of `area` will be `number | undefined` instead. + +Also, unlike Haskell, common properties show up in any union, so you +can usefully discriminate multiple members of the union: + +```ts twoslash +type Shape = + | { kind: "circle"; radius: number } + | { kind: "square"; x: number } + | { kind: "triangle"; x: number; y: number }; +// ---cut--- +function height(s: Shape) { + if (s.kind === "circle") { + return 2 * s.radius; + } else { + // s.kind: "square" | "triangle" + return s.x; + } +} +``` + +## Type Parameters + +Like most C-descended languages, TypeScript requires declaration of +type parameters: + +```ts +function liftArray(t: T): Array { + return [t]; +} +``` + +There is no case requirement, but type parameters are conventionally +single uppercase letters. Type parameters can also be constrained to a +type, which behaves a bit like type class constraints: + +```ts +function firstish(t1: T, t2: T): T { + return t1.length > t2.length ? t1 : t2; +} +``` + +TypeScript can usually infer type arguments from a call based on the +type of the arguments, so type arguments are usually not needed. + +Because TypeScript is structural, it doesn't need type parameters as +much as nominal systems. Specifically, they are not needed to make a +function polymorphic. Type parameters should only be used to +_propagate_ type information, such as constraining parameters to be +the same type: + +```ts +function length>(t: T): number {} + +function length(t: ArrayLike): number {} +``` + +In the first `length`, T is not necessary; notice that it's only +referenced once, so it's not being used to constrain the type of the +return value or other parameters. + +### Higher-kinded types + +TypeScript does not have higher kinded types, so the following is not legal: + +```ts +function length, U>(m: T) {} +``` + +### Point-free programming + +Point-free programming — heavy use of currying and function +composition — is possible in JavaScript, but can be verbose. +In TypeScript, type inference often fails for point-free programs, so +you'll end up specifying type parameters instead of value parameters. The +result is so verbose that it's usually better to avoid point-free +programming. + +## Module system + +JavaScript's modern module syntax is a bit like Haskell's, except that +any file with `import` or `export` is implicitly a module: + +```ts +import { value, Type } from "npm-package"; +import { other, Types } from "./local-package"; +import * as prefix from "../lib/third-package"; +``` + +You can also import commonjs modules — modules written using node.js' +module system: + +```ts +import f = require("single-function-package"); +``` + +You can export with an export list: + +```ts +export { f }; + +function f() { + return g(); +} +function g() {} // g is not exported +``` + +Or by marking each export individually: + +```ts +export function f { return g() } +function g() { } +``` + +The latter style is more common but both are allowed, even in the same +file. + +## `readonly` and `const` + +In JavaScript, mutability is the default, although it allows variable +declarations with `const` to declare that the _reference_ is +immutable. The referent is still mutable: + +```js +const a = [1, 2, 3]; +a.push(102); // ): +a[0] = 101; // D: +``` + +TypeScript additionally has a `readonly` modifier for properties. + +```ts +interface Rx { + readonly x: number; +} +let rx: Rx = { x: 1 }; +rx.x = 12; // error +``` + +It also ships with a mapped type `Readonly` that makes +all properties `readonly`: + +```ts +interface X { + x: number; +} +let rx: Readonly = { x: 1 }; +rx.x = 12; // error +``` + +And it has a specific `ReadonlyArray` type that removes +side-affecting methods and prevents writing to indices of the array, +as well as special syntax for this type: + +```ts +let a: ReadonlyArray = [1, 2, 3]; +let b: readonly number[] = [1, 2, 3]; +a.push(102); // error +b[0] = 101; // error +``` + +You can also use a const-assertion, which operates on arrays and +object literals: + +```ts +let a = [1, 2, 3] as const; +a.push(102); // error +a[0] = 101; // error +``` + +However, none of these options are the default, so they are not +consistently used in TypeScript code. + +## Next Steps + +This doc is a high level overview of the syntax and types you would use in everyday code. From here you should: + +- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m) +- Explore the [Playground examples](/play#show-examples) diff --git a/docs/documentation/zh/get-started/TS for JS Programmers.md b/docs/documentation/zh/get-started/TS for JS Programmers.md new file mode 100644 index 00000000..1c70140f --- /dev/null +++ b/docs/documentation/zh/get-started/TS for JS Programmers.md @@ -0,0 +1,289 @@ +--- +title: TypeScript for JavaScript Programmers +short: TypeScript for JS Programmers +layout: docs +permalink: /docs/handbook/typescript-in-5-minutes.html +oneline: Learn how TypeScript extends JavaScript +--- + +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. + +For example, JavaScript provides language primitives like `string` and `number`, but it doesn't check that you've consistently assigned these. TypeScript does. + +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. + +This tutorial provides a brief overview of TypeScript, focusing on its type system. + +## 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. + +```ts twoslash +let helloWorld = "Hello World"; +// ^? +``` + +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. + +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. + +## 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. + +For example, to create an object with an inferred type which includes `name: string` and `id: number`, you can write: + +```ts twoslash +const user = { + name: "Hayes", + id: 0, +}; +``` + +You can explicitly describe this object's shape using an `interface` declaration: + +```ts twoslash +interface User { + name: string; + id: number; +} +``` + +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: + +```ts twoslash +interface User { + name: string; + id: number; +} +// ---cut--- +const user: User = { + name: "Hayes", + id: 0, +}; +``` + +If you provide an object that doesn't match the interface you have provided, TypeScript will warn you: + +```ts twoslash +// @errors: 2322 +interface User { + name: string; + id: number; +} + +const user: User = { + username: "Hayes", + id: 0, +}; +``` + +Since JavaScript supports classes and object-oriented programming, so does TypeScript. You can use an interface declaration with classes: + +```ts twoslash +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); +``` + +You can use interfaces to annotate parameters and return values to functions: + +```ts twoslash +// @noErrors +interface User { + name: string; + id: number; +} +// ---cut--- +function getAdminUser(): User { + //... +} + +function deleteUser(user: User) { + // ... +} +``` + +There are already a small set of primitive types available in JavaScript: `boolean`, `bigint`, `null`, `number`, `string`, `symbol`, and `undefined`, which you can use in an interface. TypeScript extends this list with a few more, such as `any` (allow anything), [`unknown`](/play#example/unknown-and-never) (ensure someone using this type declares what the type is), [`never`](/play#example/unknown-and-never) (it's not possible that this type could happen), and `void` (a function which returns `undefined` or has no return value). + +You'll see that there are two syntaxes for building types: [Interfaces and Types](/play/?e=83#example/types-vs-interfaces). You should prefer `interface`. Use `type` when you need specific features. + +## 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. + +### 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`: + +```ts twoslash +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. + +A popular use-case for union types is to describe the set of `string` or `number` [literals](/docs/handbook/literal-types.html) that a value is allowed to be: + +```ts twoslash +type WindowStates = "open" | "closed" | "minimized"; +type LockStates = "locked" | "unlocked"; +type PositiveOddNumbersUnderTen = 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`: + +```ts twoslash +function getLength(obj: string | string[]) { + return obj.length; +} +``` + +To learn the type of a variable, use `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: + + +```ts twoslash +function wrapInArray(obj: string | string[]) { + if (typeof obj === "string") { + return [obj]; +// ^? + } + return obj; +} +``` + +### Generics + +Generics provide variables to types. 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. + +```ts +type StringArray = Array; +type NumberArray = Array; +type ObjectWithNameArray = Array<{ name: string }>; +``` + +You can declare your own types that use generics: + +```ts twoslash +// @errors: 2345 +interface Backpack { + 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; + +// 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); +``` + +## 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". + +In a structural type system, if two objects have the same shape, they are considered to be of the same type. + +```ts twoslash +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); +``` + +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. + +The shape-matching only requires a subset of the object's fields to match. + +```ts twoslash +// @errors: 2345 +interface Point { + x: number; + y: number; +} + +function logPoint(p: Point) { + console.log(`${p.x}, ${p.y}`); +} +// ---cut--- +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); +``` + +There is no difference between how classes and objects conform to shapes: + +```ts twoslash +// @errors: 2345 +interface Point { + x: number; + y: number; +} + +function logPoint(p: Point) { + console.log(`${p.x}, ${p.y}`); +} +// ---cut--- +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" +``` + +If the object or class has all the required properties, TypeScript will say they match, regardless of the implementation details. + +## Next Steps + +This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can: + +- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m) +- Explore the [Playground examples](/play#show-examples) diff --git a/docs/documentation/zh/get-started/TS for OOPers.md b/docs/documentation/zh/get-started/TS for OOPers.md new file mode 100644 index 00000000..9e3891f3 --- /dev/null +++ b/docs/documentation/zh/get-started/TS for OOPers.md @@ -0,0 +1,194 @@ +--- +title: TypeScript for Java/C# Programmers +short: TS for Java/C# Programmers +layout: docs +permalink: /docs/handbook/typescript-in-5-minutes-oop.html +oneline: Learn TypeScript if you have a background in object-oriented languages +--- + +TypeScript is a popular choice for programmers accustomed to other languages with static typing, such as C# and Java. + +TypeScript's type system offers many of the same benefits, such as better code completion, earlier detection of errors, and clearer communication between parts of your program. +While TypeScript provides many familiar features for these developers, it's worth stepping back to see how JavaScript (and therefore TypeScript) differ from traditional OOP languages. +Understanding these differences will help you write better JavaScript code, and avoid common pitfalls that programmers who go straight from C#/Java to TypeScript may fall in to. + +## Co-learning JavaScript + +If you're familiar with JavaScript already but are primarily a Java or C# programmer, this introductory page can help explain some of the common misconceptions and pitfalls you might be susceptible to. +Some of the ways that TypeScript models types are quite different from Java or C#, and it's important to keep these in mind when learning TypeScript. + +If you're a Java or C# programmer that is new to JavaScript in general, we recommend learning a little bit of JavaScript _without_ types first to understand JavaScript's runtime behaviors. +Because TypeScript doesn't change how your code _runs_, you'll still have to learn how JavaScript works in order to write code that actually does something! + +It's important to remember that TypeScript uses the same _runtime_ as JavaScript, so any resources about how to accomplish specific runtime behavior (converting a string to a number, displaying an alert, writing a file to disk, etc.) will always apply equally well to TypeScript programs. +Don't limit yourself to TypeScript-specific resources! + +## Rethinking the Class + +C# and Java are what we might call _mandatory OOP_ languages. +In these languages, the _class_ is the basic unit of code organization, and also the basic container of all data _and_ behavior at runtime. +Forcing all functionality and data to be held in classes can be a good domain model for some problems, but not every domain _needs_ to be represented this way. + +### Free Functions and Data + +In JavaScript, functions can live anywhere, and data can be passed around freely without being inside a pre-defined `class` or `struct`. +This flexibility is extremely powerful. +"Free" functions (those not associated with a class) working over data without an implied OOP hierarchy tends to be the preferred model for writing programs in JavaScript. + +### Static Classes + +Additionally, certain constructs from C# and Java such as singletons and static classes are unnecessary in TypeScript. + +## OOP in TypeScript + +That said, you can still use classes if you like! +Some problems are well-suited to being solved by a traditional OOP hierarchy, and TypeScript's support for JavaScript classes will make these models even more powerful. +TypeScript supports many common patterns such as implementing interfaces, inheritance, and static methods. + +We'll cover classes later in this guide. + +## Rethinking Types + +TypeScript's understanding of a _type_ is actually quite different from C# or Java's. +Let's explore some differences. + +### Nominal Reified Type Systems + +In C# or Java, any given value or object has one exact type - either `null`, a primitive, or a known class type. +We can call methods like `value.GetType()` or `value.getClass()` to query the exact type at runtime. +The definition of this type will reside in a class somewhere with some name, and we can't use two classes with similar shapes in lieu of each other unless there's an explicit inheritance relationship or commonly-implemented interface. + +These aspects describe a _reified, nominal_ type system. +The types we wrote in the code are present at runtime, and the types are related via their declarations, not their structures. + +### Types as Sets + +In C# or Java, it's meaningful to think of a one-to-one correspondence between runtime types and their compile-time declarations. + +In TypeScript, it's better to think of a type as a _set of values_ that share something in common. +Because types are just sets, a particular value can belong to _many_ sets at the same time. + +Once you start thinking of types as sets, certain operations become very natural. +For example, in C#, it's awkward to pass around a value that is _either_ a `string` or `int`, because there isn't a single type that represents this sort of value. + +In TypeScript, this becomes very natural once you realize that every type is just a set. +How do you describe a value that either belongs in the `string` set or the `number` set? +It simply belongs to the _union_ of those sets: `string | number`. + +TypeScript provides a number of mechanisms to work with types in a set-theoretic way, and you'll find them more intuitive if you think of types as sets. + +### Erased Structural Types + +In TypeScript, objects are _not_ of a single exact type. +For example, if we construct an object that satisfies an interface, we can use that object where that interface is expected even though there was no declarative relationship between the two. + +```ts twoslash +interface Pointlike { + x: number; + y: number; +} +interface Named { + name: string; +} + +function logPoint(point: Pointlike) { + console.log("x = " + point.x + ", y = " + point.y); +} + +function logName(x: Named) { + console.log("Hello, " + x.name); +} + +const obj = { + x: 0, + y: 0, + name: "Origin", +}; + +logPoint(obj); +logName(obj); +``` + +TypeScript's type system is _structural_, not nominal: We can use `obj` as a `Pointlike` because it has `x` and `y` properties that are both numbers. +The relationships between types are determined by the properties they contain, not whether they were declared with some particular relationship. + +TypeScript's type system is also _not reified_: There's nothing at runtime that will tell us that `obj` is `Pointlike`. +In fact, the `Pointlike` type is not present _in any form_ at runtime. + +Going back to the idea of _types as sets_, we can think of `obj` as being a member of both the `Pointlike` set of values and the `Named` set of values. + +### Consequences of Structural Typing + +OOP programmers are often surprised by two particular aspects of structural typing. + +#### Empty Types + +The first is that the _empty type_ seems to defy expectation: + +```ts twoslash +class Empty {} + +function fn(arg: Empty) { + // do something? +} + +// No error, but this isn't an 'Empty' ? +fn({ k: 10 }); +``` + +TypeScript determines if the call to `fn` here is valid by seeing if the provided argument is a valid `Empty`. +It does so by examining the _structure_ of `{ k: 10 }` and `class Empty { }`. +We can see that `{ k: 10 }` has _all_ of the properties that `Empty` does, because `Empty` has no properties. +Therefore, this is a valid call! + +This may seem surprising, but it's ultimately a very similar relationship to one enforced in nominal OOP languages. +A subclass cannot _remove_ a property of its base class, because doing so would destroy the natural subtype relationship between the derived class and its base. +Structural type systems simply identify this relationship implicitly by describing subtypes in terms of having properties of compatible types. + +#### Identical Types + +Another frequent source of surprise comes with identical types: + +```ts +class Car { + drive() { + // hit the gas + } +} +class Golfer { + drive() { + // hit the ball far + } +} + +// No error? +let w: Car = new Golfer(); +``` + +Again, this isn't an error because the _structures_ of these classes are the same. +While this may seem like a potential source of confusion, in practice, identical classes that shouldn't be related are not common. + +We'll learn more about how classes relate to each other in the Classes chapter. + +### Reflection + +OOP programmers are accustomed to being able to query the type of any value, even a generic one: + +```csharp +// C# +static void LogType() { + Console.WriteLine(typeof(T).Name); +} +``` + +Because TypeScript's type system is fully erased, information about e.g. the instantiation of a generic type parameter is not available at runtime. + +JavaScript does have some limited primitives like `typeof` and `instanceof`, but remember that these operators are still working on the values as they exist in the type-erased output code. +For example, `typeof (new Car())` will be `"object"`, not `Car` or `"Car"`. + +## Next Steps + +This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can: + +- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m) +- Explore the [Playground examples](/play#show-examples) diff --git a/docs/documentation/zh/get-started/TS for the New Programmer.md b/docs/documentation/zh/get-started/TS for the New Programmer.md new file mode 100644 index 00000000..d000a6b3 --- /dev/null +++ b/docs/documentation/zh/get-started/TS for the New Programmer.md @@ -0,0 +1,194 @@ +--- +title: TypeScript for the New Programmer +short: TS for the New Programmer +layout: docs +permalink: /docs/handbook/typescript-from-scratch.html +oneline: Learn TypeScript from scratch +--- + +Congratulations on choosing TypeScript as one of your first languages — you're already making good decisions! + +You've probably already heard that TypeScript is a "flavor" or "variant" of JavaScript. +The relationship between TypeScript (TS) and JavaScript (JS) is rather unique among modern programming languages, so learning more about this relationship will help you understand how TypeScript adds to JavaScript. + +## What is JavaScript? A Brief History + +JavaScript (also known as ECMAScript) started its life as a simple scripting language for browsers. +At the time it was invented, it was expected to be used for short snippets of code embedded in a web page — writing more than a few dozen lines of code would have been somewhat unusual. +Due to this, early web browsers executed such code pretty slowly. +Over time, though, JS became more and more popular, and web developers started using it to create interactive experiences. + +Web browser developers responded to this increased JS usage by optimizing their execution engines (dynamic compilation) and extending what could be done with it (adding APIs), which in turn made web developers use it even more. +On modern websites, your browser is frequently running applications that span hundreds of thousands of lines of code. +This is long and gradual growth of "the web", starting as a simple network of static pages, and evolving into a platform for rich _applications_ of all kinds. + +More than this, JS has become popular enough to be used outside the context of browsers, such as implementing JS servers using node.js. +The "run anywhere" nature of JS makes it an attractive choice for cross-platform development. +There are many developers these days that use _only_ JavaScript to program their entire stack! + +To summarize, we have a language that was designed for quick uses, and then grew to a full-fledged tool to write applications with millions of lines. +Every language has its own _quirks_ — oddities and surprises, and JavaScript's humble beginning makes it have _many_ of these. Some examples: + +- JavaScript's equality operator (`==`) _coerces_ its arguments, leading to unexpected behavior: + + ```js + if ("" == 0) { + // It is! But why?? + } + if (1 < x < 3) { + // True for *any* value of x! + } + ``` + +- JavaScript also allows accessing properties which aren't present: + + ```js + const obj = { width: 10, height: 15 }; + // Why is this NaN? Spelling is hard! + const area = obj.width * obj.heigth; + ``` + +Most programming languages would throw an error when these sorts of errors occur, some would do so during compilation — before any code is running. +When writing small programs, such quirks are annoying but manageable; when writing applications with hundreds or thousands of lines of code, these constant surprises are a serious problem. + +## TypeScript: A Static Type Checker + +We said earlier that some languages wouldn't allow those buggy programs to run at all. +Detecting errors in code without running it is referred to as _static checking_. +Determining what's an error and what's not based on the kinds of values being operated on is known as static _type_ checking. + +TypeScript checks a program for errors before execution, and does so based on the _kinds of values_, it's a _static type checker_. +For example, the last example above has an error because of the _type_ of `obj`. +Here's the error TypeScript found: + +```ts twoslash +// @errors: 2551 +const obj = { width: 10, height: 15 }; +const area = obj.width * obj.heigth; +``` + +### A Typed Superset of JavaScript + +How does TypeScript relate to JavaScript, though? + +#### Syntax + +TypeScript is a language that is a _superset_ of JavaScript: JS syntax is therefore legal TS. +Syntax refers to the way we write text to form a program. +For example, this code has a _syntax_ error because it's missing a `)`: + +```ts twoslash +// @errors: 1005 +let a = (4 +``` + +TypeScript doesn't consider any JavaScript code to be an error because of its syntax. +This means you can take any working JavaScript code and put it in a TypeScript file without worrying about exactly how it is written. + +#### Types + +However, TypeScript is a _typed_ superset, meaning that it adds rules about how different kinds of values can be used. +The earlier error about `obj.heigth` was not a _syntax_ error: it is an error of using some kind of value (a _type_) in an incorrect way. + +As another example, this is JavaScript code that you can run in your browser, and it _will_ log a value: + +```js +console.log(4 / []); +``` + +This syntactically-legal program logs `Infinity`. +TypeScript, though, considers division of number by an array to be a nonsensical operation, and will issue an error: + +```ts twoslash +// @errors: 2363 +console.log(4 / []); +``` + +It's possible you really _did_ intend to divide a number by an array, perhaps just to see what happens, but most of the time, though, this is a programming mistake. +TypeScript's type checker is designed to allow correct programs through while still catching as many common errors as possible. +(Later, we'll learn about settings you can use to configure how strictly TypeScript checks your code.) + +If you move some code from a JavaScript file to a TypeScript file, you might see _type errors_ depending on how the code is written. +These may be legitimate problems with the code, or TypeScript being overly conservative. +Throughout this guide we'll demonstrate how to add various TypeScript syntax to eliminate such errors. + +#### Runtime Behavior + +TypeScript is also a programming language that preserves the _runtime behavior_ of JavaScript. +For example, dividing by zero in JavaScript produces `Infinity` instead of throwing a runtime exception. +As a principle, TypeScript **never** changes the runtime behavior of JavaScript code. + +This means that if you move code from JavaScript to TypeScript, it is **guaranteed** to run the same way, even if TypeScript thinks that the code has type errors. + +Keeping the same runtime behavior as JavaScript is a foundational promise of TypeScript because it means you can easily transition between the two languages without worrying about subtle differences that might make your program stop working. + + + +#### Erased Types + +Roughly speaking, once TypeScript's compiler is done with checking your code, it _erases_ the types to produce the resulting "compiled" code. +This means that once your code is compiled, the resulting plain JS code has no type information. + +This also means that TypeScript never changes the _behavior_ of your program based on the types it inferred. +The bottom line is that while you might see type errors during compilation, the type system itself has no bearing on how your program works when it runs. + +Finally, TypeScript doesn't provide any additional runtime libraries. +Your programs will use the same standard library (or external libraries) as JavaScript programs, so there's no additional TypeScript-specific framework to learn. + + + +## Learning JavaScript and TypeScript + +We frequently see the question "Should I learn JavaScript or TypeScript?". + +The answer is that you can't learn TypeScript without learning JavaScript! +TypeScript shares syntax and runtime behavior with JavaScript, so anything you learn about JavaScript is helping you learn TypeScript at the same time. + +There are many, many resources available for programmers to learn JavaScript; you should _not_ ignore these resources if you're writing TypeScript. +For example, there are about 20 times more StackOverflow questions tagged `javascript` than `typescript`, but _all_ of the `javascript` questions also apply to TypeScript. + +If you find yourself searching for something like "how to sort a list in TypeScript", remember: **TypeScript is JavaScript's runtime with a compile-time type checker**. +The way you sort a list in TypeScript is the same way you do so in JavaScript. +If you find a resource that uses TypeScript directly, that's great too, but don't limit yourself to thinking you need TypeScript-specific answers for everyday questions about how to accomplish runtime tasks. + +## Next Steps + +This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can: + +- Learn some of the JavaScript fundamentals, we recommend either: + + - [Microsoft's JavaScript Resources](https://docs.microsoft.com/javascript/) or + - [JavaScript guide at the Mozilla Web Docs](https://developer.mozilla.org/docs/Web/JavaScript/Guide) + +- Continue to [TypeScript for JavaScript Programmers](/docs/handbook/typescript-in-5-minutes.html) +- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m) +- Explore the [Playground examples](/play#show-examples) + + + diff --git a/docs/documentation/zh/handbook-v1/Basic Types.md b/docs/documentation/zh/handbook-v1/Basic Types.md new file mode 100644 index 00000000..3ae3fb63 --- /dev/null +++ b/docs/documentation/zh/handbook-v1/Basic Types.md @@ -0,0 +1,417 @@ +--- +title: Basic Types +layout: docs +permalink: /docs/handbook/basic-types.html +oneline: "Step two in learning TypeScript: The basic types." +handbook: "true" +deprecated_by: /docs/handbook/2/everyday-types.html +# prettier-ignore +deprecation_redirects: [ + never, /docs/handbook/2/narrowing.html#the-never-type, + unknown, /docs/handbook/2/functions.html#unknown, + void, /docs/handbook/2/functions.html#void +] +--- + +For programs to be useful, we need to be able to work with some of the simplest units of data: numbers, strings, structures, boolean values, and the like. +In TypeScript, we support the same types as you would expect in JavaScript, with an extra enumeration type thrown in to help things along. + +## Boolean + +The most basic datatype is the simple true/false value, which JavaScript and TypeScript call a `boolean` value. + +```ts twoslash +let isDone: boolean = false; +``` + +## Number + +As in JavaScript, all numbers in TypeScript are either floating point values or BigIntegers. +These floating point numbers get the type `number`, while BigIntegers get the type `bigint`. +In addition to hexadecimal and decimal literals, TypeScript also supports binary and octal literals introduced in ECMAScript 2015. + +```ts twoslash +// @target: ES2020 +let decimal: number = 6; +let hex: number = 0xf00d; +let binary: number = 0b1010; +let octal: number = 0o744; +let big: bigint = 100n; +``` + +## String + +Another fundamental part of creating programs in JavaScript for webpages and servers alike is working with textual data. +As in other languages, we use the type `string` to refer to these textual datatypes. +Just like JavaScript, TypeScript also uses double quotes (`"`) or single quotes (`'`) to surround string data. + +```ts twoslash +let color: string = "blue"; +// prettier-ignore +color = 'red'; +``` + +You can also use _template strings_, which can span multiple lines and have embedded expressions. +These strings are surrounded by the backtick/backquote (`` ` ``) character, and embedded expressions are of the form `${ expr }`. + +```ts twoslash +let fullName: string = `Bob Bobbington`; +let age: number = 37; +let sentence: string = `Hello, my name is ${fullName}. + +I'll be ${age + 1} years old next month.`; +``` + +This is equivalent to declaring `sentence` like so: + +```ts twoslash +let fullName: string = `Bob Bobbington`; +let age: number = 37; +// ---cut--- +let sentence: string = + "Hello, my name is " + + fullName + + ".\n\n" + + "I'll be " + + (age + 1) + + " years old next month."; +``` + +## Array + +TypeScript, like JavaScript, allows you to work with arrays of values. +Array types can be written in one of two ways. +In the first, you use the type of the elements followed by `[]` to denote an array of that element type: + +```ts twoslash +let list: number[] = [1, 2, 3]; +``` + +The second way uses a generic array type, `Array`: + +```ts twoslash +let list: Array = [1, 2, 3]; +``` + +## Tuple + +Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same. For example, you may want to represent a value as a pair of a `string` and a `number`: + +```ts twoslash +// @errors: 2322 +// Declare a tuple type +let x: [string, number]; +// Initialize it +x = ["hello", 10]; // OK +// Initialize it incorrectly +x = [10, "hello"]; // Error +``` + +When accessing an element with a known index, the correct type is retrieved: + +```ts twoslash +// @errors: 2339 +let x: [string, number]; +x = ["hello", 10]; // OK +/// ---cut--- +// OK +console.log(x[0].substring(1)); + +console.log(x[1].substring(1)); +``` + +Accessing an element outside the set of known indices fails with an error: + +```ts twoslash +// @errors: 2493 2532 2322 +let x: [string, number]; +x = ["hello", 10]; // OK +/// ---cut--- +x[3] = "world"; + +console.log(x[5].toString()); +``` + +## Enum + +A helpful addition to the standard set of datatypes from JavaScript is the `enum`. +As in languages like C#, an enum is a way of giving more friendly names to sets of numeric values. + +```ts twoslash +enum Color { + Red, + Green, + Blue, +} +let c: Color = Color.Green; +``` + +By default, enums begin numbering their members starting at `0`. +You can change this by manually setting the value of one of its members. +For example, we can start the previous example at `1` instead of `0`: + +```ts twoslash +enum Color { + Red = 1, + Green, + Blue, +} +let c: Color = Color.Green; +``` + +Or, even manually set all the values in the enum: + +```ts twoslash +enum Color { + Red = 1, + Green = 2, + Blue = 4, +} +let c: Color = Color.Green; +``` + +A handy feature of enums is that you can also go from a numeric value to the name of that value in the enum. +For example, if we had the value `2` but weren't sure what that mapped to in the `Color` enum above, we could look up the corresponding name: + +```ts twoslash +enum Color { + Red = 1, + Green, + Blue, +} +let colorName: string = Color[2]; + +// Displays 'Green' +console.log(colorName); +``` + +## Unknown + +We may need to describe the type of variables that we do not know when we are writing an application. +These values may come from dynamic content – e.g. from the user – or we may want to intentionally accept all values in our API. +In these cases, we want to provide a type that tells the compiler and future readers that this variable could be anything, so we give it the `unknown` type. + +```ts twoslash +let notSure: unknown = 4; +notSure = "maybe a string instead"; + +// OK, definitely a boolean +notSure = false; +``` + +If you have a variable with an unknown type, you can narrow it to something more specific by doing `typeof` checks, comparison checks, or more advanced type guards that will be discussed in a later chapter: + +```ts twoslash +// @errors: 2322 2322 2322 +declare const maybe: unknown; +// 'maybe' could be a string, object, boolean, undefined, or other types +const aNumber: number = maybe; + +if (maybe === true) { + // TypeScript knows that maybe is a boolean now + const aBoolean: boolean = maybe; + // So, it cannot be a string + const aString: string = maybe; +} + +if (typeof maybe === "string") { + // TypeScript knows that maybe is a string + const aString: string = maybe; + // So, it cannot be a boolean + const aBoolean: boolean = maybe; +} +``` + +## Any + +In some situations, not all type information is available or its declaration would take an inappropriate amount of effort. +These may occur for values from code that has been written without TypeScript or a 3rd party library. +In these cases, we might want to opt-out of type checking. +To do so, we label these values with the `any` type: + +```ts twoslash +declare function getValue(key: string): any; +// OK, return value of 'getValue' is not checked +const str: string = getValue("myString"); +``` + +The `any` type is a powerful way to work with existing JavaScript, allowing you to gradually opt-in and opt-out of type checking during compilation. + +Unlike `unknown`, variables of type `any` allow you to access arbitrary properties, even ones that don't exist. +These properties include functions and TypeScript will not check their existence or type: + +```ts twoslash +// @errors: 2571 +let looselyTyped: any = 4; +// OK, ifItExists might exist at runtime +looselyTyped.ifItExists(); +// OK, toFixed exists (but the compiler doesn't check) +looselyTyped.toFixed(); + +let strictlyTyped: unknown = 4; +strictlyTyped.toFixed(); +``` + +The `any` will continue to propagate through your objects: + +```ts twoslash +let looselyTyped: any = {}; +let d = looselyTyped.a.b.c.d; +// ^? +``` + +After all, remember that all the convenience of `any` comes at the cost of losing type safety. +Type safety is one of the main motivations for using TypeScript and you should try to avoid using `any` when not necessary. + +## Void + +`void` is a little like the opposite of `any`: the absence of having any type at all. +You may commonly see this as the return type of functions that do not return a value: + +```ts twoslash +function warnUser(): void { + console.log("This is my warning message"); +} +``` + +Declaring variables of type `void` is not useful because you can only assign `null` (only if `--strictNullChecks` is not specified, see next section) or `undefined` to them: + +```ts twoslash +// @strict: false +let unusable: void = undefined; +// OK if `--strictNullChecks` is not given +unusable = null; +``` + +## Null and Undefined + +In TypeScript, both `undefined` and `null` actually have their types named `undefined` and `null` respectively. +Much like `void`, they're not extremely useful on their own: + +```ts twoslash +// Not much else we can assign to these variables! +let u: undefined = undefined; +let n: null = null; +``` + +By default `null` and `undefined` are subtypes of all other types. +That means you can assign `null` and `undefined` to something like `number`. + +However, when using the `--strictNullChecks` flag, `null` and `undefined` are only assignable to `unknown`, `any` and their respective types (the one exception being that `undefined` is also assignable to `void`). +This helps avoid _many_ common errors. +In cases where you want to pass in either a `string` or `null` or `undefined`, you can use the union type `string | null | undefined`. + +Union types are an advanced topic that we'll cover in a later chapter. + +> As a note: we encourage the use of `--strictNullChecks` when possible, but for the purposes of this handbook, we will assume it is turned off. + +## Never + +The `never` type represents the type of values that never occur. +For instance, `never` is the return type for a function expression or an arrow function expression that always throws an exception or one that never returns. +Variables also acquire the type `never` when narrowed by any type guards that can never be true. + +The `never` type is a subtype of, and assignable to, every type; however, _no_ type is a subtype of, or assignable to, `never` (except `never` itself). +Even `any` isn't assignable to `never`. + +Some examples of functions returning `never`: + +```ts twoslash +// Function returning never must not have a reachable end point +function error(message: string): never { + throw new Error(message); +} + +// Inferred return type is never +function fail() { + return error("Something failed"); +} + +// Function returning never must not have a reachable end point +function infiniteLoop(): never { + while (true) {} +} +``` + +## Object + +`object` is a type that represents the non-primitive type, i.e. anything that is not `number`, `string`, `boolean`, `bigint`, `symbol`, `null`, or `undefined`. + +With `object` type, APIs like `Object.create` can be better represented. For example: + +```ts twoslash +// @errors: 2345 +declare function create(o: object | null): void; + +// OK +create({ prop: 0 }); +create(null); +create(undefined); // with `--strictNullChecks` flag enabled, undefined is not a subtype of null + +create(42); +create("string"); +create(false); +``` + +Generally, you won't need to use this. + +## Type assertions + +Sometimes you'll end up in a situation where you'll know more about a value than TypeScript does. +Usually, this will happen when you know the type of some entity could be more specific than its current type. + +_Type assertions_ are a way to tell the compiler "trust me, I know what I'm doing." +A type assertion is like a type cast in other languages, but it performs no special checking or restructuring of data. +It has no runtime impact and is used purely by the compiler. +TypeScript assumes that you, the programmer, have performed any special checks that you need. + +Type assertions have two forms. + +One is the `as`-syntax: + +```ts twoslash +let someValue: unknown = "this is a string"; + +let strLength: number = (someValue as string).length; +``` + +The other version is the "angle-bracket" syntax: + +```ts twoslash +let someValue: unknown = "this is a string"; + +let strLength: number = (someValue).length; +``` + +The two samples are equivalent. +Using one over the other is mostly a choice of preference; however, when using TypeScript with JSX, only `as`-style assertions are allowed. + +## A note about `let` + +You may have noticed that so far, we've been using the `let` keyword instead of JavaScript's `var` keyword which you might be more familiar with. +The `let` keyword is actually a newer JavaScript construct that TypeScript makes available. +You can read in the Handbook Reference on [Variable Declarations](/docs/handbook/variable-declarations.html) more about how `let` and `const` fix a lot of the problems with `var`. + +## About `Number`, `String`, `Boolean`, `Symbol` and `Object` + +It can be tempting to think that the types `Number`, `String`, `Boolean`, `Symbol`, or `Object` are the same as the lowercase versions recommended above. +These types do not refer to the language primitives however, and almost never should be used as a type. + +```ts twoslash +// @errors: 2339 +function reverse(s: String): String { + return s.split("").reverse().join(""); +} + +reverse("hello world"); +``` + +Instead, use the types `number`, `string`, `boolean`, `object` and `symbol`. + +```ts twoslash +function reverse(s: string): string { + return s.split("").reverse().join(""); +} + +reverse("hello world"); +``` diff --git a/docs/documentation/zh/handbook-v1/Classes.md b/docs/documentation/zh/handbook-v1/Classes.md new file mode 100644 index 00000000..f0e368c9 --- /dev/null +++ b/docs/documentation/zh/handbook-v1/Classes.md @@ -0,0 +1,611 @@ +--- +title: Classes +layout: docs +permalink: /docs/handbook/classes.html +oneline: How classes work in TypeScript +handbook: "true" +deprecated_by: /docs/handbook/2/classes.html +--- + +Traditional JavaScript uses functions and prototype-based inheritance to build up reusable components, but this may feel a bit awkward to programmers more comfortable with an object-oriented approach, where classes inherit functionality and objects are built from these classes. +Starting with ECMAScript 2015, also known as ECMAScript 6, JavaScript programmers can build their applications using this object-oriented class-based approach. +In TypeScript, we allow developers to use these techniques now, and compile them down to JavaScript that works across all major browsers and platforms, without having to wait for the next version of JavaScript. + +## Classes + +Let's take a look at a simple class-based example: + +```ts twoslash +class Greeter { + greeting: string; + + constructor(message: string) { + this.greeting = message; + } + + greet() { + return "Hello, " + this.greeting; + } +} + +let greeter = new Greeter("world"); +``` + +The syntax should look familiar if you've used C# or Java before. +We declare a new class `Greeter`. This class has three members: a property called `greeting`, a constructor, and a method `greet`. + +You'll notice that in the class when we refer to one of the members of the class we prepend `this.`. +This denotes that it's a member access. + +In the last line we construct an instance of the `Greeter` class using `new`. +This calls into the constructor we defined earlier, creating a new object with the `Greeter` shape, and running the constructor to initialize it. + +## Inheritance + +In TypeScript, we can use common object-oriented patterns. +One of the most fundamental patterns in class-based programming is being able to extend existing classes to create new ones using inheritance. + +Let's take a look at an example: + +```ts twoslash +class Animal { + move(distanceInMeters: number = 0) { + console.log(`Animal moved ${distanceInMeters}m.`); + } +} + +class Dog extends Animal { + bark() { + console.log("Woof! Woof!"); + } +} + +const dog = new Dog(); +dog.bark(); +dog.move(10); +dog.bark(); +``` + +This example shows the most basic inheritance feature: classes inherit properties and methods from base classes. +Here, `Dog` is a _derived_ class that derives from the `Animal` _base_ class using the `extends` keyword. +Derived classes are often called _subclasses_, and base classes are often called _superclasses_. + +Because `Dog` extends the functionality from `Animal`, we were able to create an instance of `Dog` that could both `bark()` and `move()`. + +Let's now look at a more complex example. + +```ts twoslash +class Animal { + name: string; + constructor(theName: string) { + this.name = theName; + } + move(distanceInMeters: number = 0) { + console.log(`${this.name} moved ${distanceInMeters}m.`); + } +} + +class Snake extends Animal { + constructor(name: string) { + super(name); + } + move(distanceInMeters = 5) { + console.log("Slithering..."); + super.move(distanceInMeters); + } +} + +class Horse extends Animal { + constructor(name: string) { + super(name); + } + move(distanceInMeters = 45) { + console.log("Galloping..."); + super.move(distanceInMeters); + } +} + +let sam = new Snake("Sammy the Python"); +let tom: Animal = new Horse("Tommy the Palomino"); + +sam.move(); +tom.move(34); +``` + +This example covers a few other features we didn't previously mention. +Again, we see the `extends` keywords used to create two new subclasses of `Animal`: `Horse` and `Snake`. + +One difference from the prior example is that each derived class that contains a constructor function _must_ call `super()` which will execute the constructor of the base class. +What's more, before we _ever_ access a property on `this` in a constructor body, we _have_ to call `super()`. +This is an important rule that TypeScript will enforce. + +The example also shows how to override methods in the base class with methods that are specialized for the subclass. +Here both `Snake` and `Horse` create a `move` method that overrides the `move` from `Animal`, giving it functionality specific to each class. +Note that even though `tom` is declared as an `Animal`, since its value is a `Horse`, calling `tom.move(34)` will call the overriding method in `Horse`: + +``` +Slithering... +Sammy the Python moved 5m. +Galloping... +Tommy the Palomino moved 34m. +``` + +## Public, private, and protected modifiers + +## Public by default + +In our examples, we've been able to freely access the members that we declared throughout our programs. +If you're familiar with classes in other languages, you may have noticed in the above examples we haven't had to use the word `public` to accomplish this; for instance, C# requires that each member be explicitly labeled `public` to be visible. +In TypeScript, each member is `public` by default. + +You may still mark a member `public` explicitly. +We could have written the `Animal` class from the previous section in the following way: + +```ts twoslash +class Animal { + public name: string; + + public constructor(theName: string) { + this.name = theName; + } + + public move(distanceInMeters: number) { + console.log(`${this.name} moved ${distanceInMeters}m.`); + } +} +``` + +## ECMAScript Private Fields + +With TypeScript 3.8, TypeScript supports the new JavaScript syntax for private fields: + +```ts twoslash +// @errors: 18013 +class Animal { + #name: string; + constructor(theName: string) { + this.#name = theName; + } +} + +new Animal("Cat").#name; +``` + +This syntax is built into the JavaScript runtime and can have better guarantees about the isolation of each private field. +Right now, the best documentation for these private fields is in the TypeScript 3.8 [release notes](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields). + +## Understanding TypeScript's `private` + +TypeScript also has its own way to declare a member as being marked `private`, it cannot be accessed from outside of its containing class. For example: + +```ts twoslash +// @errors: 2341 +class Animal { + private name: string; + + constructor(theName: string) { + this.name = theName; + } +} + +new Animal("Cat").name; +``` + +TypeScript is a structural type system. +When we compare two different types, regardless of where they came from, if the types of all members are compatible, then we say the types themselves are compatible. + +However, when comparing types that have `private` and `protected` members, we treat these types differently. +For two types to be considered compatible, if one of them has a `private` member, then the other must have a `private` member that originated in the same declaration. +The same applies to `protected` members. + +Let's look at an example to better see how this plays out in practice: + +```ts twoslash +// @errors: 2322 +class Animal { + private name: string; + constructor(theName: string) { + this.name = theName; + } +} + +class Rhino extends Animal { + constructor() { + super("Rhino"); + } +} + +class Employee { + private name: string; + constructor(theName: string) { + this.name = theName; + } +} + +let animal = new Animal("Goat"); +let rhino = new Rhino(); +let employee = new Employee("Bob"); + +animal = rhino; +animal = employee; +``` + +In this example, we have an `Animal` and a `Rhino`, with `Rhino` being a subclass of `Animal`. +We also have a new class `Employee` that looks identical to `Animal` in terms of shape. +We create some instances of these classes and then try to assign them to each other to see what will happen. +Because `Animal` and `Rhino` share the `private` side of their shape from the same declaration of `private name: string` in `Animal`, they are compatible. However, this is not the case for `Employee`. +When we try to assign from an `Employee` to `Animal` we get an error that these types are not compatible. +Even though `Employee` also has a `private` member called `name`, it's not the one we declared in `Animal`. + +## Understanding `protected` + +The `protected` modifier acts much like the `private` modifier with the exception that members declared `protected` can also be accessed within deriving classes. For example, + +```ts twoslash +// @errors: 2445 +class Person { + protected name: string; + constructor(name: string) { + this.name = name; + } +} + +class Employee extends Person { + private department: string; + + constructor(name: string, department: string) { + super(name); + this.department = department; + } + + public getElevatorPitch() { + return `Hello, my name is ${this.name} and I work in ${this.department}.`; + } +} + +let howard = new Employee("Howard", "Sales"); +console.log(howard.getElevatorPitch()); +console.log(howard.name); +``` + +Notice that while we can't use `name` from outside of `Person`, we can still use it from within an instance method of `Employee` because `Employee` derives from `Person`. + +A constructor may also be marked `protected`. +This means that the class cannot be instantiated outside of its containing class, but can be extended. For example, + +```ts twoslash +// @errors: 2674 +class Person { + protected name: string; + protected constructor(theName: string) { + this.name = theName; + } +} + +// Employee can extend Person +class Employee extends Person { + private department: string; + + constructor(name: string, department: string) { + super(name); + this.department = department; + } + + public getElevatorPitch() { + return `Hello, my name is ${this.name} and I work in ${this.department}.`; + } +} + +let howard = new Employee("Howard", "Sales"); +let john = new Person("John"); +``` + +## Readonly modifier + +You can make properties readonly by using the `readonly` keyword. +Readonly properties must be initialized at their declaration or in the constructor. + +```ts twoslash +// @errors: 2540 +class Octopus { + readonly name: string; + readonly numberOfLegs: number = 8; + + constructor(theName: string) { + this.name = theName; + } +} + +let dad = new Octopus("Man with the 8 strong legs"); +dad.name = "Man with the 3-piece suit"; +``` + +## Parameter properties + +In our last example, we had to declare a readonly member `name` and a constructor parameter `theName` in the `Octopus` class. This is needed in order to have the value of `theName` accessible after the `Octopus` constructor is executed. +_Parameter properties_ let you create and initialize a member in one place. +Here's a further revision of the previous `Octopus` class using a parameter property: + +```ts twoslash +class Octopus { + readonly numberOfLegs: number = 8; + constructor(readonly name: string) {} +} + +let dad = new Octopus("Man with the 8 strong legs"); +dad.name; +``` + +Notice how we dropped `theName` altogether and just use the shortened `readonly name: string` parameter on the constructor to create and initialize the `name` member. +We've consolidated the declarations and assignment into one location. + +Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or `readonly`, or both. +Using `private` for a parameter property declares and initializes a private member; likewise, the same is done for `public`, `protected`, and `readonly`. + +## Accessors + +TypeScript supports getters/setters as a way of intercepting accesses to a member of an object. +This gives you a way of having finer-grained control over how a member is accessed on each object. + +Let's convert a simple class to use `get` and `set`. +First, let's start with an example without getters and setters. + +```ts twoslash +// @strict: false +class Employee { + fullName: string; +} + +let employee = new Employee(); +employee.fullName = "Bob Smith"; + +if (employee.fullName) { + console.log(employee.fullName); +} +``` + +While allowing people to randomly set `fullName` directly is pretty handy, we may also want enforce some constraints when `fullName` is set. + +In this version, we add a setter that checks the length of the `newName` to make sure it's compatible with the max-length of our backing database field. If it isn't we throw an error notifying client code that something went wrong. + +To preserve existing functionality, we also add a simple getter that retrieves `fullName` unmodified. + +```ts twoslash +// @strict: false +const fullNameMaxLength = 10; + +class Employee { + private _fullName: string = ""; + + get fullName(): string { + return this._fullName; + } + + set fullName(newName: string) { + if (newName && newName.length > fullNameMaxLength) { + throw new Error("fullName has a max length of " + fullNameMaxLength); + } + + this._fullName = newName; + } +} + +let employee = new Employee(); +employee.fullName = "Bob Smith"; + +if (employee.fullName) { + console.log(employee.fullName); +} +``` + +To prove to ourselves that our accessor is now checking the length of values, we can attempt to assign a name longer than 10 characters and verify that we get an error. + +A couple of things to note about accessors: + +First, accessors require you to set the compiler to output ECMAScript 5 or higher. +Downleveling to ECMAScript 3 is not supported. +Second, accessors with a `get` and no `set` are automatically inferred to be `readonly`. +This is helpful when generating a `.d.ts` file from your code, because users of your property can see that they can't change it. + +## Static Properties + +Up to this point, we've only talked about the _instance_ members of the class, those that show up on the object when it's instantiated. +We can also create _static_ members of a class, those that are visible on the class itself rather than on the instances. +In this example, we use `static` on the origin, as it's a general value for all grids. +Each instance accesses this value through prepending the name of the class. +Similarly to prepending `this.` in front of instance accesses, here we prepend `Grid.` in front of static accesses. + +```ts twoslash +class Grid { + static origin = { x: 0, y: 0 }; + + calculateDistanceFromOrigin(point: { x: number; y: number }) { + let xDist = point.x - Grid.origin.x; + let yDist = point.y - Grid.origin.y; + return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale; + } + + constructor(public scale: number) {} +} + +let grid1 = new Grid(1.0); // 1x scale +let grid2 = new Grid(5.0); // 5x scale + +console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 })); +console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 })); +``` + +## Abstract Classes + +Abstract classes are base classes from which other classes may be derived. +They may not be instantiated directly. +Unlike an interface, an abstract class may contain implementation details for its members. +The `abstract` keyword is used to define abstract classes as well as abstract methods within an abstract class. + +```ts twoslash +abstract class Animal { + abstract makeSound(): void; + + move(): void { + console.log("roaming the earth..."); + } +} +``` + +Methods within an abstract class that are marked as abstract do not contain an implementation and must be implemented in derived classes. +Abstract methods share a similar syntax to interface methods. +Both define the signature of a method without including a method body. +However, abstract methods must include the `abstract` keyword and may optionally include access modifiers. + +```ts twoslash +// @errors: 2511 2339 +abstract class Department { + constructor(public name: string) {} + + printName(): void { + console.log("Department name: " + this.name); + } + + abstract printMeeting(): void; // must be implemented in derived classes +} + +class AccountingDepartment extends Department { + constructor() { + super("Accounting and Auditing"); // constructors in derived classes must call super() + } + + printMeeting(): void { + console.log("The Accounting Department meets each Monday at 10am."); + } + + generateReports(): void { + console.log("Generating accounting reports..."); + } +} + +let department: Department; // ok to create a reference to an abstract type +department = new Department(); // error: cannot create an instance of an abstract class +department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass +department.printName(); +department.printMeeting(); +department.generateReports(); // error: department is not of type AccountingDepartment, cannot access generateReports +``` + +## Advanced Techniques + +## Constructor functions + +When you declare a class in TypeScript, you are actually creating multiple declarations at the same time. +The first is the type of the _instance_ of the class. + +```ts twoslash +class Greeter { + greeting: string; + + constructor(message: string) { + this.greeting = message; + } + + greet() { + return "Hello, " + this.greeting; + } +} + +let greeter: Greeter; +greeter = new Greeter("world"); +console.log(greeter.greet()); // "Hello, world" +``` + +Here, when we say `let greeter: Greeter`, we're using `Greeter` as the type of instances of the class `Greeter`. +This is almost second nature to programmers from other object-oriented languages. + +We're also creating another value that we call the _constructor function_. +This is the function that is called when we `new` up instances of the class. +To see what this looks like in practice, let's take a look at the JavaScript created by the above example: + +```ts twoslash +// @strict: false +let Greeter = (function () { + function Greeter(message) { + this.greeting = message; + } + + Greeter.prototype.greet = function () { + return "Hello, " + this.greeting; + }; + + return Greeter; +})(); + +let greeter; +greeter = new Greeter("world"); +console.log(greeter.greet()); // "Hello, world" +``` + +Here, `let Greeter` is going to be assigned the constructor function. +When we call `new` and run this function, we get an instance of the class. +The constructor function also contains all of the static members of the class. +Another way to think of each class is that there is an _instance_ side and a _static_ side. + +Let's modify the example a bit to show this difference: + +```ts twoslash +// @strict: false +class Greeter { + static standardGreeting = "Hello, there"; + greeting: string; + greet() { + if (this.greeting) { + return "Hello, " + this.greeting; + } else { + return Greeter.standardGreeting; + } + } +} + +let greeter1: Greeter; +greeter1 = new Greeter(); +console.log(greeter1.greet()); // "Hello, there" + +let greeterMaker: typeof Greeter = Greeter; +greeterMaker.standardGreeting = "Hey there!"; + +let greeter2: Greeter = new greeterMaker(); +console.log(greeter2.greet()); // "Hey there!" + +let greeter3: Greeter; +greeter3 = new Greeter(); +console.log(greeter3.greet()); // "Hey there!" +``` + +In this example, `greeter1` works similarly to before. +We instantiate the `Greeter` class, and use this object. +This we have seen before. + +Next, we then use the class directly. +Here we create a new variable called `greeterMaker`. +This variable will hold the class itself, or said another way its constructor function. +Here we use `typeof Greeter`, that is "give me the type of the `Greeter` class itself" rather than the instance type. +Or, more precisely, "give me the type of the symbol called `Greeter`," which is the type of the constructor function. +This type will contain all of the static members of Greeter along with the constructor that creates instances of the `Greeter` class. +We show this by using `new` on `greeterMaker`, creating new instances of `Greeter` and invoking them as before. +It is also good to mention that changing static property is frowned upon, here `greeter3` has `"Hey there!"` instead of `"Hello, there"` on `standardGreeting`. + +## Using a class as an interface + +As we said in the previous section, a class declaration creates two things: a type representing instances of the class and a constructor function. +Because classes create types, you can use them in the same places you would be able to use interfaces. + +```ts twoslash +// @strict: false +class Point { + x: number; + y: number; +} + +interface Point3d extends Point { + z: number; +} + +let point3d: Point3d = { x: 1, y: 2, z: 3 }; +``` diff --git a/docs/documentation/zh/handbook-v1/Functions.md b/docs/documentation/zh/handbook-v1/Functions.md new file mode 100644 index 00000000..ffbed924 --- /dev/null +++ b/docs/documentation/zh/handbook-v1/Functions.md @@ -0,0 +1,546 @@ +--- +title: Functions +layout: docs +permalink: /docs/handbook/functions.html +oneline: How to add types to a function +handbook: "true" +deprecated_by: /docs/handbook/2/functions.html +--- + +Functions are the fundamental building block of any application in JavaScript. +They're how you build up layers of abstraction, mimicking classes, information hiding, and modules. +In TypeScript, while there are classes, namespaces, and modules, functions still play the key role in describing how to _do_ things. +TypeScript also adds some new capabilities to the standard JavaScript functions to make them easier to work with. + +## Functions + +To begin, just as in JavaScript, TypeScript functions can be created both as a named function or as an anonymous function. +This allows you to choose the most appropriate approach for your application, whether you're building a list of functions in an API or a one-off function to hand off to another function. + +To quickly recap what these two approaches look like in JavaScript: + +```ts twoslash +// @strict: false +// Named function +function add(x, y) { + return x + y; +} + +// Anonymous function +let myAdd = function (x, y) { + return x + y; +}; +``` + +Just as in JavaScript, functions can refer to variables outside of the function body. +When they do so, they're said to _capture_ these variables. +While understanding how this works (and the trade-offs when using this technique) is outside of the scope of this article, having a firm understanding how this mechanic works is an important piece of working with JavaScript and TypeScript. + +```ts twoslash +// @strict: false +let z = 100; + +function addToZ(x, y) { + return x + y + z; +} +``` + +## Function Types + +## Typing the function + +Let's add types to our simple examples from earlier: + +```ts twoslash +function add(x: number, y: number): number { + return x + y; +} + +let myAdd = function (x: number, y: number): number { + return x + y; +}; +``` + +We can add types to each of the parameters and then to the function itself to add a return type. +TypeScript can figure the return type out by looking at the return statements, so we can also optionally leave this off in many cases. + +## Writing the function type + +Now that we've typed the function, let's write the full type of the function out by looking at each piece of the function type. + +```ts twoslash +let myAdd: (x: number, y: number) => number = function ( + x: number, + y: number +): number { + return x + y; +}; +``` + +A function's type has the same two parts: the type of the arguments and the return type. +When writing out the whole function type, both parts are required. +We write out the parameter types just like a parameter list, giving each parameter a name and a type. +This name is just to help with readability. +We could have instead written: + +```ts twoslash +let myAdd: (baseValue: number, increment: number) => number = function ( + x: number, + y: number +): number { + return x + y; +}; +``` + +As long as the parameter types line up, it's considered a valid type for the function, regardless of the names you give the parameters in the function type. + +The second part is the return type. +We make it clear which is the return type by using an arrow (`=>`) between the parameters and the return type. +As mentioned before, this is a required part of the function type, so if the function doesn't return a value, you would use `void` instead of leaving it off. + +Of note, only the parameters and the return type make up the function type. +Captured variables are not reflected in the type. +In effect, captured variables are part of the "hidden state" of any function and do not make up its API. + +## Inferring the types + +In playing with the example, you may notice that the TypeScript compiler can figure out the type even if you only have types on one side of the equation: + +```ts twoslash +// The parameters 'x' and 'y' have the type number +let myAdd = function (x: number, y: number): number { + return x + y; +}; + +// myAdd has the full function type +let myAdd2: (baseValue: number, increment: number) => number = function (x, y) { + return x + y; +}; +``` + +This is called "contextual typing", a form of type inference. +This helps cut down on the amount of effort to keep your program typed. + +## Optional and Default Parameters + +In TypeScript, every parameter is assumed to be required by the function. +This doesn't mean that it can't be given `null` or `undefined`, but rather, when the function is called, the compiler will check that the user has provided a value for each parameter. +The compiler also assumes that these parameters are the only parameters that will be passed to the function. +In short, the number of arguments given to a function has to match the number of parameters the function expects. + +```ts twoslash +// @errors: 2554 +function buildName(firstName: string, lastName: string) { + return firstName + " " + lastName; +} + +let result1 = buildName("Bob"); // error, too few parameters +let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters +let result3 = buildName("Bob", "Adams"); // ah, just right +``` + +In JavaScript, every parameter is optional, and users may leave them off as they see fit. +When they do, their value is `undefined`. +We can get this functionality in TypeScript by adding a `?` to the end of parameters we want to be optional. +For example, let's say we want the last name parameter from above to be optional: + +```ts twoslash +// @errors: 2554 +function buildName(firstName: string, lastName?: string) { + if (lastName) return firstName + " " + lastName; + else return firstName; +} + +let result1 = buildName("Bob"); // works correctly now +let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters +let result3 = buildName("Bob", "Adams"); // ah, just right +``` + +Any optional parameters must follow required parameters. +Had we wanted to make the first name optional, rather than the last name, we would need to change the order of parameters in the function, putting the first name last in the list. + +In TypeScript, we can also set a value that a parameter will be assigned if the user does not provide one, or if the user passes `undefined` in its place. +These are called default-initialized parameters. +Let's take the previous example and default the last name to `"Smith"`. + +```ts twoslash +// @errors: 2554 +function buildName(firstName: string, lastName = "Smith") { + return firstName + " " + lastName; +} + +let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith" +let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith" +let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameters +let result4 = buildName("Bob", "Adams"); // ah, just right +``` + +Default-initialized parameters that come after all required parameters are treated as optional, and just like optional parameters, can be omitted when calling their respective function. +This means optional parameters and trailing default parameters will share commonality in their types, so both + +```ts +function buildName(firstName: string, lastName?: string) { + // ... +} +``` + +and + +```ts +function buildName(firstName: string, lastName = "Smith") { + // ... +} +``` + +share the same type `(firstName: string, lastName?: string) => string`. +The default value of `lastName` disappears in the type, only leaving behind the fact that the parameter is optional. + +Unlike plain optional parameters, default-initialized parameters don't _need_ to occur after required parameters. +If a default-initialized parameter comes before a required parameter, users need to explicitly pass `undefined` to get the default initialized value. +For example, we could write our last example with only a default initializer on `firstName`: + +```ts twoslash +// @errors: 2554 +function buildName(firstName = "Will", lastName: string) { + return firstName + " " + lastName; +} + +let result1 = buildName("Bob"); // error, too few parameters +let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters +let result3 = buildName("Bob", "Adams"); // okay and returns "Bob Adams" +let result4 = buildName(undefined, "Adams"); // okay and returns "Will Adams" +``` + +## Rest Parameters + +Required, optional, and default parameters all have one thing in common: they talk about one parameter at a time. +Sometimes, you want to work with multiple parameters as a group, or you may not know how many parameters a function will ultimately take. +In JavaScript, you can work with the arguments directly using the `arguments` variable that is visible inside every function body. + +In TypeScript, you can gather these arguments together into a variable: + +```ts twoslash +function buildName(firstName: string, ...restOfName: string[]) { + return firstName + " " + restOfName.join(" "); +} + +// employeeName will be "Joseph Samuel Lucas MacKinzie" +let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie"); +``` + +_Rest parameters_ are treated as a boundless number of optional parameters. +When passing arguments for a rest parameter, you can use as many as you want; you can even pass none. +The compiler will build an array of the arguments passed in with the name given after the ellipsis (`...`), allowing you to use it in your function. + +The ellipsis is also used in the type of the function with rest parameters: + +```ts twoslash +function buildName(firstName: string, ...restOfName: string[]) { + return firstName + " " + restOfName.join(" "); +} + +let buildNameFun: (fname: string, ...rest: string[]) => string = buildName; +``` + +## `this` + +Learning how to use `this` in JavaScript is something of a rite of passage. +Since TypeScript is a superset of JavaScript, TypeScript developers also need to learn how to use `this` and how to spot when it's not being used correctly. +Fortunately, TypeScript lets you catch incorrect uses of `this` with a couple of techniques. +If you need to learn how `this` works in JavaScript, though, first read Yehuda Katz's [Understanding JavaScript Function Invocation and "this"](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/). +Yehuda's article explains the inner workings of `this` very well, so we'll just cover the basics here. + +## `this` and arrow functions + +In JavaScript, `this` is a variable that's set when a function is called. +This makes it a very powerful and flexible feature, but it comes at the cost of always having to know about the context that a function is executing in. +This is notoriously confusing, especially when returning a function or passing a function as an argument. + +Let's look at an example: + +```ts twoslash +// @strict: false +let deck = { + suits: ["hearts", "spades", "clubs", "diamonds"], + cards: Array(52), + createCardPicker: function () { + return function () { + let pickedCard = Math.floor(Math.random() * 52); + let pickedSuit = Math.floor(pickedCard / 13); + + return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; + }; + }, +}; + +let cardPicker = deck.createCardPicker(); +let pickedCard = cardPicker(); + +alert("card: " + pickedCard.card + " of " + pickedCard.suit); +``` + +Notice that `createCardPicker` is a function that itself returns a function. +If we tried to run the example, we would get an error instead of the expected alert box. +This is because the `this` being used in the function created by `createCardPicker` will be set to `window` instead of our `deck` object. +That's because we call `cardPicker()` on its own. +A top-level non-method syntax call like this will use `window` for `this`. +(Note: under strict mode, `this` will be `undefined` rather than `window`). + +We can fix this by making sure the function is bound to the correct `this` before we return the function to be used later. +This way, regardless of how it's later used, it will still be able to see the original `deck` object. +To do this, we change the function expression to use the ECMAScript 6 arrow syntax. +Arrow functions capture the `this` where the function is created rather than where it is invoked: + +```ts twoslash +// @strict: false +let deck = { + suits: ["hearts", "spades", "clubs", "diamonds"], + cards: Array(52), + createCardPicker: function () { + // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here + return () => { + let pickedCard = Math.floor(Math.random() * 52); + let pickedSuit = Math.floor(pickedCard / 13); + + return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; + }; + }, +}; + +let cardPicker = deck.createCardPicker(); +let pickedCard = cardPicker(); + +alert("card: " + pickedCard.card + " of " + pickedCard.suit); +``` + +Even better, TypeScript will warn you when you make this mistake if you pass the `--noImplicitThis` flag to the compiler. +It will point out that `this` in `this.suits[pickedSuit]` is of type `any`. + +## `this` parameters + +Unfortunately, the type of `this.suits[pickedSuit]` is still `any`. +That's because `this` comes from the function expression inside the object literal. +To fix this, you can provide an explicit `this` parameter. +`this` parameters are fake parameters that come first in the parameter list of a function: + +```ts +function f(this: void) { + // make sure `this` is unusable in this standalone function +} +``` + +Let's add a couple of interfaces to our example above, `Card` and `Deck`, to make the types clearer and easier to reuse: + +```ts twoslash +interface Card { + suit: string; + card: number; +} + +interface Deck { + suits: string[]; + cards: number[]; + createCardPicker(this: Deck): () => Card; +} + +let deck: Deck = { + suits: ["hearts", "spades", "clubs", "diamonds"], + cards: Array(52), + // NOTE: The function now explicitly specifies that its callee must be of type Deck + createCardPicker: function (this: Deck) { + return () => { + let pickedCard = Math.floor(Math.random() * 52); + let pickedSuit = Math.floor(pickedCard / 13); + + return { suit: this.suits[pickedSuit], card: pickedCard % 13 }; + }; + }, +}; + +let cardPicker = deck.createCardPicker(); +let pickedCard = cardPicker(); + +alert("card: " + pickedCard.card + " of " + pickedCard.suit); +``` + +Now TypeScript knows that `createCardPicker` expects to be called on a `Deck` object. +That means that `this` is of type `Deck` now, not `any`, so `--noImplicitThis` will not cause any errors. + +### `this` parameters in callbacks + +You can also run into errors with `this` in callbacks, when you pass functions to a library that will later call them. +Because the library that calls your callback will call it like a normal function, `this` will be `undefined`. +With some work you can use `this` parameters to prevent errors with callbacks too. +First, the library author needs to annotate the callback type with `this`: + +```ts twoslash +interface UIElement { + addClickListener(onclick: (this: void, e: Event) => void): void; +} +``` + +`this: void` means that `addClickListener` expects `onclick` to be a function that does not require a `this` type. +Second, annotate your calling code with `this`: + +```ts twoslash +// @strict: false +// @errors: 2345 +interface UIElement { + addClickListener(onclick: (this: void, e: Event) => void): void; +} +interface Event { + message: string; +} +declare const uiElement: UIElement; +// ---cut--- +class Handler { + info: string; + onClickBad(this: Handler, e: Event) { + // oops, used `this` here. using this callback would crash at runtime + this.info = e.message; + } +} + +let h = new Handler(); +uiElement.addClickListener(h.onClickBad); // error! +``` + +With `this` annotated, you make it explicit that `onClickBad` must be called on an instance of `Handler`. +Then TypeScript will detect that `addClickListener` requires a function that has `this: void`. +To fix the error, change the type of `this`: + +```ts twoslash +// @strict: false +interface UIElement { + addClickListener(onclick: (this: void, e: Event) => void): void; +} +interface Event { + message: string; +} +declare const uiElement: UIElement; +// ---cut--- +class Handler { + info: string; + onClickGood(this: void, e: Event) { + // can't use `this` here because it's of type void! + console.log("clicked!"); + } +} + +let h = new Handler(); +uiElement.addClickListener(h.onClickGood); +``` + +Because `onClickGood` specifies its `this` type as `void`, it is legal to pass to `addClickListener`. +Of course, this also means that it can't use `this.info`. +If you want both then you'll have to use an arrow function: + +```ts twoslash +// @strict: false +interface UIElement { + addClickListener(onclick: (this: void, e: Event) => void): void; +} +interface Event { + message: string; +} +declare const uiElement: UIElement; +// ---cut--- +class Handler { + info: string; + onClickGood = (e: Event) => { + this.info = e.message; + }; +} +``` + +This works because arrow functions use the outer `this`, so you can always pass them to something that expects `this: void`. +The downside is that one arrow function is created per object of type Handler. +Methods, on the other hand, are only created once and attached to Handler's prototype. +They are shared between all objects of type Handler. + +## Overloads + +JavaScript is inherently a very dynamic language. +It's not uncommon for a single JavaScript function to return different types of objects based on the shape of the arguments passed in. + +```ts twoslash +// @strict: false +let suits = ["hearts", "spades", "clubs", "diamonds"]; + +function pickCard(x: any): any { + // Check to see if we're working with an object/array + // if so, they gave us the deck and we'll pick the card + if (typeof x == "object") { + let pickedCard = Math.floor(Math.random() * x.length); + return pickedCard; + } + // Otherwise just let them pick the card + else if (typeof x == "number") { + let pickedSuit = Math.floor(x / 13); + return { suit: suits[pickedSuit], card: x % 13 }; + } +} + +let myDeck = [ + { suit: "diamonds", card: 2 }, + { suit: "spades", card: 10 }, + { suit: "hearts", card: 4 }, +]; + +let pickedCard1 = myDeck[pickCard(myDeck)]; +alert("card: " + pickedCard1.card + " of " + pickedCard1.suit); + +let pickedCard2 = pickCard(15); +alert("card: " + pickedCard2.card + " of " + pickedCard2.suit); +``` + +Here, the `pickCard` function will return two different things based on what the user has passed in. +If the users passes in an object that represents the deck, the function will pick the card. +If the user picks the card, we tell them which card they've picked. +But how do we describe this to the type system? + +The answer is to supply multiple function types for the same function as a list of overloads. +This list is what the compiler will use to resolve function calls. +Let's create a list of overloads that describe what our `pickCard` accepts and what it returns. + +```ts twoslash +let suits = ["hearts", "spades", "clubs", "diamonds"]; + +function pickCard(x: { suit: string; card: number }[]): number; +function pickCard(x: number): { suit: string; card: number }; +function pickCard(x: any): any { + // Check to see if we're working with an object/array + // if so, they gave us the deck and we'll pick the card + if (typeof x == "object") { + let pickedCard = Math.floor(Math.random() * x.length); + return pickedCard; + } + // Otherwise just let them pick the card + else if (typeof x == "number") { + let pickedSuit = Math.floor(x / 13); + return { suit: suits[pickedSuit], card: x % 13 }; + } +} + +let myDeck = [ + { suit: "diamonds", card: 2 }, + { suit: "spades", card: 10 }, + { suit: "hearts", card: 4 }, +]; + +let pickedCard1 = myDeck[pickCard(myDeck)]; +alert("card: " + pickedCard1.card + " of " + pickedCard1.suit); + +let pickedCard2 = pickCard(15); +alert("card: " + pickedCard2.card + " of " + pickedCard2.suit); +``` + +With this change, the overloads now give us type checked calls to the `pickCard` function. + +In order for the compiler to pick the correct type check, it follows a similar process to the underlying JavaScript. +It looks at the overload list and, proceeding with the first overload, attempts to call the function with the provided parameters. +If it finds a match, it picks this overload as the correct overload. +For this reason, it's customary to order overloads from most specific to least specific. + +Note that the `function pickCard(x): any` piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number. +Calling `pickCard` with any other parameter types would cause an error. diff --git a/docs/documentation/zh/handbook-v1/Generics.md b/docs/documentation/zh/handbook-v1/Generics.md new file mode 100644 index 00000000..a5f7bd40 --- /dev/null +++ b/docs/documentation/zh/handbook-v1/Generics.md @@ -0,0 +1,376 @@ +--- +title: Generics +layout: docs +permalink: /docs/handbook/generics.html +oneline: Introduction to TypeScript and Generics +handbook: "true" +deprecated_by: /docs/handbook/2/generics.html +--- + +A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable. +Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems. + +In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is _generics_, that is, being able to create a component that can work over a variety of types rather than a single one. +This allows users to consume these components and use their own types. + +## Hello World of Generics + +To start off, let's do the "hello world" of generics: the identity function. +The identity function is a function that will return back whatever is passed in. +You can think of this in a similar way to the `echo` command. + +Without generics, we would either have to give the identity function a specific type: + +```ts twoslash +function identity(arg: number): number { + return arg; +} +``` + +Or, we could describe the identity function using the `any` type: + +```ts twoslash +function identity(arg: any): any { + return arg; +} +``` + +While using `any` is certainly generic in that it will cause the function to accept any and all types for the type of `arg`, we actually are losing the information about what that type was when the function returns. +If we passed in a number, the only information we have is that any type could be returned. + +Instead, we need a way of capturing the type of the argument in such a way that we can also use it to denote what is being returned. +Here, we will use a _type variable_, a special kind of variable that works on types rather than values. + +```ts twoslash +function identity(arg: T): T { + return arg; +} +``` + +We've now added a type variable `T` to the identity function. +This `T` allows us to capture the type the user provides (e.g. `number`), so that we can use that information later. +Here, we use `T` again as the return type. On inspection, we can now see the same type is used for the argument and the return type. +This allows us to traffic that type information in one side of the function and out the other. + +We say that this version of the `identity` function is generic, as it works over a range of types. +Unlike using `any`, it's also just as precise (ie, it doesn't lose any information) as the first `identity` function that used numbers for the argument and return type. + +Once we've written the generic identity function, we can call it in one of two ways. +The first way is to pass all of the arguments, including the type argument, to the function: + +```ts twoslash +function identity(arg: T): T { + return arg; +} +// ---cut--- +let output = identity("myString"); +// ^? +``` + +Here we explicitly set `T` to be `string` as one of the arguments to the function call, denoted using the `<>` around the arguments rather than `()`. + +The second way is also perhaps the most common. Here we use _type argument inference_ -- that is, we want the compiler to set the value of `T` for us automatically based on the type of the argument we pass in: + +```ts twoslash +function identity(arg: T): T { + return arg; +} +// ---cut--- +let output = identity("myString"); +// ^? +``` + +Notice that we didn't have to explicitly pass the type in the angle brackets (`<>`); the compiler just looked at the value `"myString"`, and set `T` to its type. +While type argument inference can be a helpful tool to keep code shorter and more readable, you may need to explicitly pass in the type arguments as we did in the previous example when the compiler fails to infer the type, as may happen in more complex examples. + +## Working with Generic Type Variables + +When you begin to use generics, you'll notice that when you create generic functions like `identity`, the compiler will enforce that you use any generically typed parameters in the body of the function correctly. +That is, that you actually treat these parameters as if they could be any and all types. + +Let's take our `identity` function from earlier: + +```ts twoslash +function identity(arg: T): T { + return arg; +} +``` + +What if we want to also log the length of the argument `arg` to the console with each call? +We might be tempted to write this: + +```ts twoslash +// @errors: 2339 +function loggingIdentity(arg: T): T { + console.log(arg.length); + return arg; +} +``` + +When we do, the compiler will give us an error that we're using the `.length` member of `arg`, but nowhere have we said that `arg` has this member. +Remember, we said earlier that these type variables stand in for any and all types, so someone using this function could have passed in a `number` instead, which does not have a `.length` member. + +Let's say that we've actually intended this function to work on arrays of `T` rather than `T` directly. Since we're working with arrays, the `.length` member should be available. +We can describe this just like we would create arrays of other types: + +```ts twoslash +function loggingIdentity(arg: T[]): T[] { + console.log(arg.length); + return arg; +} +``` + +You can read the type of `loggingIdentity` as "the generic function `loggingIdentity` takes a type parameter `T`, and an argument `arg` which is an array of `T`s, and returns an array of `T`s." +If we passed in an array of numbers, we'd get an array of numbers back out, as `T` would bind to `number`. +This allows us to use our generic type variable `T` as part of the types we're working with, rather than the whole type, giving us greater flexibility. + +We can alternatively write the sample example this way: + +```ts twoslash +function loggingIdentity(arg: Array): Array { + console.log(arg.length); // Array has a .length, so no more error + return arg; +} +``` + +You may already be familiar with this style of type from other languages. +In the next section, we'll cover how you can create your own generic types like `Array`. + +## Generic Types + +In previous sections, we created generic identity functions that worked over a range of types. +In this section, we'll explore the type of the functions themselves and how to create generic interfaces. + +The type of generic functions is just like those of non-generic functions, with the type parameters listed first, similarly to function declarations: + +```ts twoslash +function identity(arg: T): T { + return arg; +} + +let myIdentity: (arg: T) => T = identity; +``` + +We could also have used a different name for the generic type parameter in the type, so long as the number of type variables and how the type variables are used line up. + +```ts twoslash +function identity(arg: T): T { + return arg; +} + +let myIdentity: (arg: U) => U = identity; +``` + +We can also write the generic type as a call signature of an object literal type: + +```ts twoslash +function identity(arg: T): T { + return arg; +} + +let myIdentity: { (arg: T): T } = identity; +``` + +Which leads us to writing our first generic interface. +Let's take the object literal from the previous example and move it to an interface: + +```ts twoslash +interface GenericIdentityFn { + (arg: T): T; +} + +function identity(arg: T): T { + return arg; +} + +let myIdentity: GenericIdentityFn = identity; +``` + +In a similar example, we may want to move the generic parameter to be a parameter of the whole interface. +This lets us see what type(s) we're generic over (e.g. `Dictionary` rather than just `Dictionary`). +This makes the type parameter visible to all the other members of the interface. + +```ts twoslash +interface GenericIdentityFn { + (arg: T): T; +} + +function identity(arg: T): T { + return arg; +} + +let myIdentity: GenericIdentityFn = identity; +``` + +Notice that our example has changed to be something slightly different. +Instead of describing a generic function, we now have a non-generic function signature that is a part of a generic type. +When we use `GenericIdentityFn`, we now will also need to specify the corresponding type argument (here: `number`), effectively locking in what the underlying call signature will use. +Understanding when to put the type parameter directly on the call signature and when to put it on the interface itself will be helpful in describing what aspects of a type are generic. + +In addition to generic interfaces, we can also create generic classes. +Note that it is not possible to create generic enums and namespaces. + +## Generic Classes + +A generic class has a similar shape to a generic interface. +Generic classes have a generic type parameter list in angle brackets (`<>`) following the name of the class. + +```ts twoslash +// @strict: false +class GenericNumber { + zeroValue: T; + add: (x: T, y: T) => T; +} + +let myGenericNumber = new GenericNumber(); +myGenericNumber.zeroValue = 0; +myGenericNumber.add = function (x, y) { + return x + y; +}; +``` + +This is a pretty literal use of the `GenericNumber` class, but you may have noticed that nothing is restricting it to only use the `number` type. +We could have instead used `string` or even more complex objects. + +```ts twoslash +// @strict: false +class GenericNumber { + zeroValue: T; + add: (x: T, y: T) => T; +} +// ---cut--- +let stringNumeric = new GenericNumber(); +stringNumeric.zeroValue = ""; +stringNumeric.add = function (x, y) { + return x + y; +}; + +console.log(stringNumeric.add(stringNumeric.zeroValue, "test")); +``` + +Just as with interface, putting the type parameter on the class itself lets us make sure all of the properties of the class are working with the same type. + +As we covered in [our section on classes](/docs/handbook/classes.html), a class has two sides to its type: the static side and the instance side. +Generic classes are only generic over their instance side rather than their static side, so when working with classes, static members can not use the class's type parameter. + +## Generic Constraints + +If you remember from an earlier example, you may sometimes want to write a generic function that works on a set of types where you have some knowledge about what capabilities that set of types will have. +In our `loggingIdentity` example, we wanted to be able to access the `.length` property of `arg`, but the compiler could not prove that every type had a `.length` property, so it warns us that we can't make this assumption. + +```ts twoslash +// @errors: 2339 +function loggingIdentity(arg: T): T { + console.log(arg.length); + return arg; +} +``` + +Instead of working with any and all types, we'd like to constrain this function to work with any and all types that also have the `.length` property. +As long as the type has this member, we'll allow it, but it's required to have at least this member. +To do so, we must list our requirement as a constraint on what T can be. + +To do so, we'll create an interface that describes our constraint. +Here, we'll create an interface that has a single `.length` property and then we'll use this interface and the `extends` keyword to denote our constraint: + +```ts twoslash +interface Lengthwise { + length: number; +} + +function loggingIdentity(arg: T): T { + console.log(arg.length); // Now we know it has a .length property, so no more error + return arg; +} +``` + +Because the generic function is now constrained, it will no longer work over any and all types: + +```ts twoslash +// @errors: 2345 +interface Lengthwise { + length: number; +} + +function loggingIdentity(arg: T): T { + console.log(arg.length); + return arg; +} +// ---cut--- +loggingIdentity(3); +``` + +Instead, we need to pass in values whose type has all the required properties: + +```ts twoslash +interface Lengthwise { + length: number; +} + +function loggingIdentity(arg: T): T { + console.log(arg.length); + return arg; +} +// ---cut--- +loggingIdentity({ length: 10, value: 3 }); +``` + +## Using Type Parameters in Generic Constraints + +You can declare a type parameter that is constrained by another type parameter. +For example, here we'd like to get a property from an object given its name. +We'd like to ensure that we're not accidentally grabbing a property that does not exist on the `obj`, so we'll place a constraint between the two types: + +```ts twoslash +// @errors: 2345 +function getProperty(obj: T, key: K) { + return obj[key]; +} + +let x = { a: 1, b: 2, c: 3, d: 4 }; + +getProperty(x, "a"); +getProperty(x, "m"); +``` + +## Using Class Types in Generics + +When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions. For example, + +```ts twoslash +function create(c: { new (): T }): T { + return new c(); +} +``` + +A more advanced example uses the prototype property to infer and constrain relationships between the constructor function and the instance side of class types. + +```ts twoslash +// @strict: false +class BeeKeeper { + hasMask: boolean; +} + +class ZooKeeper { + nametag: string; +} + +class Animal { + numLegs: number; +} + +class Bee extends Animal { + keeper: BeeKeeper; +} + +class Lion extends Animal { + keeper: ZooKeeper; +} + +function createInstance(c: new () => A): A { + return new c(); +} + +createInstance(Lion).keeper.nametag; +createInstance(Bee).keeper.hasMask; +``` diff --git a/docs/documentation/zh/handbook-v1/Interfaces.md b/docs/documentation/zh/handbook-v1/Interfaces.md new file mode 100644 index 00000000..4e2707cb --- /dev/null +++ b/docs/documentation/zh/handbook-v1/Interfaces.md @@ -0,0 +1,717 @@ +--- +title: Interfaces +layout: docs +permalink: /docs/handbook/interfaces.html +oneline: How to write an interface with TypeScript +handbook: "true" +deprecated_by: /docs/handbook/2/objects.html +--- + +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 subtyping". +In TypeScript, interfaces fill the role of naming these types, and are a powerful way of defining contracts within your code as well as contracts with code outside of your project. + +## Our First Interface + +The easiest way to see how interfaces work is to start with a simple example: + +```ts twoslash +function printLabel(labeledObj: { label: string }) { + console.log(labeledObj.label); +} + +let myObj = { size: 10, label: "Size 10 Object" }; +printLabel(myObj); +``` + +The type checker checks the call to `printLabel`. +The `printLabel` function has a single parameter that requires that the object passed in has a property called `label` of type `string`. +Notice that our object actually has more properties than this, but the compiler only checks that _at least_ the ones required are present and match the types required. +There are some cases where TypeScript isn't as lenient, which we'll cover in a bit. + +We can write the same example again, this time using an interface to describe the requirement of having the `label` property that is a string: + +```ts twoslash +interface LabeledValue { + label: string; +} + +function printLabel(labeledObj: LabeledValue) { + console.log(labeledObj.label); +} + +let myObj = { size: 10, label: "Size 10 Object" }; +printLabel(myObj); +``` + +The interface `LabeledValue` is a name we can now use to describe the requirement in the previous example. +It still represents having a single property called `label` that is of type `string`. +Notice we didn't have to explicitly say that the object we pass to `printLabel` implements this interface like we might have to in other languages. +Here, it's only the shape that matters. If the object we pass to the function meets the requirements listed, then it's allowed. + +It's worth pointing out that the type checker does not require that these properties come in any sort of order, only that the properties the interface requires are present and have the required type. + +## Optional Properties + +Not all properties of an interface may be required. +Some exist under certain conditions or may not be there at all. +These optional properties are popular when creating patterns like "option bags" where you pass an object to a function that only has a couple of properties filled in. + +Here's an example of this pattern: + +```ts twoslash +interface SquareConfig { + color?: string; + width?: number; +} + +function createSquare(config: SquareConfig): { color: string; area: number } { + let newSquare = { color: "white", area: 100 }; + if (config.color) { + newSquare.color = config.color; + } + if (config.width) { + newSquare.area = config.width * config.width; + } + return newSquare; +} + +let mySquare = createSquare({ color: "black" }); +``` + +Interfaces with optional properties are written similar to other interfaces, with each optional property denoted by a `?` at the end of the property name in the declaration. + +The advantage of optional properties is that you can describe these possibly available properties while still also preventing use of properties that are not part of the interface. +For example, had we mistyped the name of the `color` property in `createSquare`, we would get an error message letting us know: + +```ts twoslash +// @errors: 2551 +interface SquareConfig { + color?: string; + width?: number; +} + +function createSquare(config: SquareConfig): { color: string; area: number } { + let newSquare = { color: "white", area: 100 }; + if (config.clor) { + // Error: Property 'clor' does not exist on type 'SquareConfig' + newSquare.color = config.clor; + } + if (config.width) { + newSquare.area = config.width * config.width; + } + return newSquare; +} + +let mySquare = createSquare({ color: "black" }); +``` + +## Readonly properties + +Some properties should only be modifiable when an object is first created. +You can specify this by putting `readonly` before the name of the property: + +```ts twoslash +interface Point { + readonly x: number; + readonly y: number; +} +``` + +You can construct a `Point` by assigning an object literal. +After the assignment, `x` and `y` can't be changed. + +```ts twoslash +// @errors: 2540 +interface Point { + readonly x: number; + readonly y: number; +} +// ---cut--- +let p1: Point = { x: 10, y: 20 }; +p1.x = 5; // error! +``` + +TypeScript comes with a `ReadonlyArray` type that is the same as `Array` with all mutating methods removed, so you can make sure you don't change your arrays after creation: + +```ts twoslash +// @errors: 2542 2339 2540 4104 +let a: number[] = [1, 2, 3, 4]; +let ro: ReadonlyArray = a; + +ro[0] = 12; // error! +ro.push(5); // error! +ro.length = 100; // error! +a = ro; // error! +``` + +On the last line of the snippet you can see that even assigning the entire `ReadonlyArray` back to a normal array is illegal. +You can still override it with a type assertion, though: + +```ts twoslash +let a: number[] = [1, 2, 3, 4]; +let ro: ReadonlyArray = a; + +a = ro as number[]; +``` + +### `readonly` vs `const` + +The easiest way to remember whether to use `readonly` or `const` is to ask whether you're using it on a variable or a property. +Variables use `const` whereas properties use `readonly`. + +## Excess Property Checks + +In our first example using interfaces, TypeScript lets us pass `{ size: number; label: string; }` to something that only expected a `{ label: string; }`. +We also just learned about optional properties, and how they're useful when describing so-called "option bags". + +However, combining the two naively would allow an error to sneak in. For example, taking our last example using `createSquare`: + +```ts twoslash +// @errors: 2345 2739 +interface SquareConfig { + color?: string; + width?: number; +} + +function createSquare(config: SquareConfig): { color: string; area: number } { + return { + color: config.color || "red", + area: config.width ? config.width * config.width : 20, + }; +} + +let mySquare = createSquare({ colour: "red", width: 100 }); +``` + +Notice the given argument to `createSquare` is spelled _`colour`_ instead of `color`. +In plain JavaScript, this sort of thing fails silently. + +You could argue that this program is correctly typed, since the `width` properties are compatible, there's no `color` property present, and the extra `colour` property is insignificant. + +However, TypeScript takes the stance that there's probably a bug in this code. +Object literals get special treatment and undergo _excess property checking_ when assigning them to other variables, or passing them as arguments. +If an object literal has any properties that the "target type" doesn't have, you'll get an error: + +```ts twoslash +// @errors: 2345 2739 +interface SquareConfig { + color?: string; + width?: number; +} + +function createSquare(config: SquareConfig): { color: string; area: number } { + return { + color: config.color || "red", + area: config.width ? config.width * config.width : 20, + }; +} +// ---cut--- +let mySquare = createSquare({ colour: "red", width: 100 }); +``` + +Getting around these checks is actually really simple. +The easiest method is to just use a type assertion: + +```ts twoslash +// @errors: 2345 2739 +interface SquareConfig { + color?: string; + width?: number; +} + +function createSquare(config: SquareConfig): { color: string; area: number } { + return { + color: config.color || "red", + area: config.width ? config.width * config.width : 20, + }; +} +// ---cut--- +let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig); +``` + +However, a better approach might be to add a string index signature if you're sure that the object can have some extra properties that are used in some special way. +If `SquareConfig` can have `color` and `width` properties with the above types, but could _also_ have any number of other properties, then we could define it like so: + +```ts twoslash +interface SquareConfig { + color?: string; + width?: number; + [propName: string]: any; +} +``` + +We'll discuss index signatures in a bit, but here we're saying a `SquareConfig` can have any number of properties, and as long as they aren't `color` or `width`, their types don't matter. + +One final way to get around these checks, which might be a bit surprising, is to assign the object to another variable: +Since `squareOptions` won't undergo excess property checks, the compiler won't give you an error. + +```ts twoslash +interface SquareConfig { + color?: string; + width?: number; + [propName: string]: any; +} + +function createSquare(config: SquareConfig): { color: string; area: number } { + return { + color: config.color || "red", + area: config.width ? config.width * config.width : 20, + }; +} +// ---cut--- +let squareOptions = { colour: "red", width: 100 }; +let mySquare = createSquare(squareOptions); +``` + +The above workaround will work as long as you have a common property between `squareOptions` and `SquareConfig`. +In this example, it was the property `width`. It will however, fail if the variable does not have any common object property. For example: + +```ts twoslash +// @errors: 2559 +interface SquareConfig { + color?: string; + width?: number; +} + +function createSquare(config: SquareConfig): { color: string; area: number } { + return { + color: config.color || "red", + area: config.width ? config.width * config.width : 20, + }; +} +// ---cut--- +let squareOptions = { colour: "red" }; +let mySquare = createSquare(squareOptions); +``` + +Keep in mind that for simple code like above, you probably shouldn't be trying to "get around" these checks. +For more complex object literals that have methods and hold state, you might need to keep these techniques in mind, but a majority of excess property errors are actually bugs. +That means if you're running into excess property checking problems for something like option bags, you might need to revise some of your type declarations. +In this instance, if it's okay to pass an object with both a `color` or `colour` property to `createSquare`, you should fix up the definition of `SquareConfig` to reflect that. + +## Function Types + +Interfaces are capable of describing the wide range of shapes that JavaScript objects can take. +In addition to describing an object with properties, interfaces are also capable of describing function types. + +To describe a function type with an interface, we give the interface a call signature. +This is like a function declaration with only the parameter list and return type given. Each parameter in the parameter list requires both name and type. + +```ts twoslash +interface SearchFunc { + (source: string, subString: string): boolean; +} +``` + +Once defined, we can use this function type interface like we would other interfaces. +Here, we show how you can create a variable of a function type and assign it a function value of the same type. + +```ts twoslash +interface SearchFunc { + (source: string, subString: string): boolean; +} +// ---cut--- +let mySearch: SearchFunc; + +mySearch = function (source: string, subString: string): boolean { + let result = source.search(subString); + return result > -1; +}; +``` + +For function types to correctly type check, the names of the parameters do not need to match. +We could have, for example, written the above example like this: + +```ts twoslash +interface SearchFunc { + (source: string, subString: string): boolean; +} +// ---cut--- +let mySearch: SearchFunc; + +mySearch = function (src: string, sub: string): boolean { + let result = src.search(sub); + return result > -1; +}; +``` + +Function parameters are checked one at a time, with the type in each corresponding parameter position checked against each other. +If you do not want to specify types at all, TypeScript's contextual typing can infer the argument types since the function value is assigned directly to a variable of type `SearchFunc`. +Here, also, the return type of our function expression is implied by the values it returns (here `false` and `true`). + +```ts twoslash +interface SearchFunc { + (source: string, subString: string): boolean; +} +// ---cut--- +let mySearch: SearchFunc; + +mySearch = function (src, sub) { + let result = src.search(sub); + return result > -1; +}; +``` + +Had the function expression returned numbers or strings, the type checker would have made an error that indicates return type doesn't match the return type described in the `SearchFunc` interface. + +```ts twoslash +// @errors: 2322 +interface SearchFunc { + (source: string, subString: string): boolean; +} +// ---cut--- +let mySearch: SearchFunc; + +mySearch = function (src, sub) { + let result = src.search(sub); + return "string"; +}; +``` + +## Indexable Types + +Similarly to how we can use interfaces to describe function types, we can also describe types that we can "index into" like `a[10]`, or `ageMap["daniel"]`. +Indexable types have an _index signature_ that describes the types we can use to index into the object, along with the corresponding return types when indexing. + +Let's take an example: + +```ts twoslash +interface StringArray { + [index: number]: string; +} + +let myArray: StringArray; +myArray = ["Bob", "Fred"]; + +let myStr: string = myArray[0]; +``` + +Above, we have a `StringArray` interface that has an index signature. +This index signature states that when a `StringArray` is indexed with a `number`, it will return a `string`. + +There are four types of supported index signatures: string, number, symbol and template strings. +It is possible to support many types of indexers, but the type returned from a numeric indexer must be a subtype of the type returned from the string indexer. + +This is because when indexing with a `number`, JavaScript will actually convert that to a `string` before indexing into an object. +That means that indexing with `100` (a `number`) is the same thing as indexing with `"100"` (a `string`), so the two need to be consistent. + +```ts twoslash +// @errors: 2413 +// @strictPropertyInitialization: false +interface Animal { + name: string; +} + +interface Dog extends Animal { + breed: string; +} + +// Error: indexing with a numeric string might get you a completely separate type of Animal! +interface NotOkay { + [x: number]: Animal; + [x: string]: Dog; +} +``` + +While string index signatures are a powerful way to describe the "dictionary" pattern, they also enforce that all properties match their return type. +This is because a string index declares that `obj.property` is also available as `obj["property"]`. +In the following example, `name`'s type does not match the string index's type, and the type checker gives an error: + +```ts twoslash +// @errors: 2411 +interface NumberDictionary { + [index: string]: number; + + length: number; // ok, length is a number + name: string; // error, the type of 'name' is not a subtype of the indexer +} +``` + +However, properties of different types are acceptable if the index signature is a union of the property types: + +```ts twoslash +interface NumberOrStringDictionary { + [index: string]: number | string; + + length: number; // ok, length is a number + name: string; // ok, name is a string +} +``` + +Finally, you can make index signatures `readonly` in order to prevent assignment to their indices: + +```ts twoslash +// @errors: 2542 +interface ReadonlyStringArray { + readonly [index: number]: string; +} + +let myArray: ReadonlyStringArray = ["Alice", "Bob"]; +myArray[2] = "Mallory"; // error! +``` + +You can't set `myArray[2]` because the index signature is `readonly`. + +### Indexable Types with Template Strings + +A template string can be used to indicate that a particular pattern is allowed, but not all. For example, a HTTP headers object may have a set list of known headers and support any [custom defined properties](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) which are prefixed with `x-`. + +```ts twoslash +// @errors: 2339 + +interface HeadersResponse { + "content-type": string, + date: string, + "content-length": string + + // Permit any property starting with 'data-'. + [headerName: `x-${string}`]: string; +} + +function handleResponse(r: HeadersResponse) { + // Handle known, and x- prefixed + const type = r["content-type"] + const poweredBy = r["x-powered-by"] + + // Unknown keys without the prefix raise errors + const origin = r.origin +} +``` + +## Class Types + +### Implementing an interface + +One of the most common uses of interfaces in languages like C# and Java, that of explicitly enforcing that a class meets a particular contract, is also possible in TypeScript. + +```ts twoslash +interface ClockInterface { + currentTime: Date; +} + +class Clock implements ClockInterface { + currentTime: Date = new Date(); + constructor(h: number, m: number) {} +} +``` + +You can also describe methods in an interface that are implemented in the class, as we do with `setTime` in the below example: + +```ts twoslash +// @strictPropertyInitialization: false +interface ClockInterface { + currentTime: Date; + setTime(d: Date): void; +} + +class Clock implements ClockInterface { + currentTime: Date = new Date(); + setTime(d: Date) { + this.currentTime = d; + } + constructor(h: number, m: number) {} +} +``` + +Interfaces describe the public side of the class, rather than both the public and private side. +This prohibits you from using them to check that a class also has particular types for the private side of the class instance. + +### Difference between the static and instance sides of classes + +When working with classes and interfaces, it helps to keep in mind that a class has _two_ types: the type of the static side and the type of the instance side. +You may notice that if you create an interface with a construct signature and try to create a class that implements this interface you get an error: + +```ts twoslash +// @errors: 7013 2420 2564 +// @strictPropertyInitialization: false +// @noImplicitAny: false +interface ClockConstructor { + new (hour: number, minute: number); +} + +class Clock implements ClockConstructor { + currentTime: Date; + constructor(h: number, m: number) {} +} +``` + +This is because when a class implements an interface, only the instance side of the class is checked. +Since the constructor sits in the static side, it is not included in this check. + +Instead, you would need to work with the static side of the class directly. +In this example, we define two interfaces, `ClockConstructor` for the constructor and `ClockInterface` for the instance methods. +Then, for convenience, we define a constructor function `createClock` that creates instances of the type that is passed to it: + +```ts twoslash +interface ClockConstructor { + new (hour: number, minute: number): ClockInterface; +} + +interface ClockInterface { + tick(): void; +} + +function createClock( + ctor: ClockConstructor, + hour: number, + minute: number +): ClockInterface { + return new ctor(hour, minute); +} + +class DigitalClock implements ClockInterface { + constructor(h: number, m: number) {} + tick() { + console.log("beep beep"); + } +} + +class AnalogClock implements ClockInterface { + constructor(h: number, m: number) {} + tick() { + console.log("tick tock"); + } +} + +let digital = createClock(DigitalClock, 12, 17); +let analog = createClock(AnalogClock, 7, 32); +``` + +Because `createClock`'s first parameter is of type `ClockConstructor`, in `createClock(AnalogClock, 7, 32)`, it checks that `AnalogClock` has the correct constructor signature. + +Another simple way is to use class expressions: + +```ts twoslash +// @strictPropertyInitialization: false +// @noImplicitAny: false +interface ClockConstructor { + new (hour: number, minute: number): ClockInterface; +} + +interface ClockInterface { + tick(): void; +} + +const Clock: ClockConstructor = class Clock implements ClockInterface { + constructor(h: number, m: number) {} + tick() { + console.log("beep beep"); + } +}; + +let clock = new Clock(12, 17); +clock.tick(); +``` + +## Extending Interfaces + +Like classes, interfaces can extend each other. +This allows you to copy the members of one interface into another, which gives you more flexibility in how you separate your interfaces into reusable components. + +```ts twoslash +interface Shape { + color: string; +} + +interface Square extends Shape { + sideLength: number; +} + +let square = {} as Square; +square.color = "blue"; +square.sideLength = 10; +``` + +An interface can extend multiple interfaces, creating a combination of all of the interfaces. + +```ts twoslash +interface Shape { + color: string; +} + +interface PenStroke { + penWidth: number; +} + +interface Square extends Shape, PenStroke { + sideLength: number; +} + +let square = {} as Square; +square.color = "blue"; +square.sideLength = 10; +square.penWidth = 5.0; +``` + +## Hybrid Types + +As we mentioned earlier, interfaces can describe the rich types present in real world JavaScript. +Because of JavaScript's dynamic and flexible nature, you may occasionally encounter an object that works as a combination of some of the types described above. + +One such example is an object that acts as both a function and an object, with additional properties: + +```ts twoslash +interface Counter { + (start: number): string; + interval: number; + reset(): void; +} + +function getCounter(): Counter { + let counter = function (start: number) {} as Counter; + counter.interval = 123; + counter.reset = function () {}; + return counter; +} + +let c = getCounter(); +c(10); +c.reset(); +c.interval = 5.0; +``` + +When interacting with 3rd-party JavaScript, you may need to use patterns like the above to fully describe the shape of the type. + +## Interfaces Extending Classes + +When an interface type extends a class type it inherits the members of the class but not their implementations. +It is as if the interface had declared all of the members of the class without providing an implementation. +Interfaces inherit even the private and protected members of a base class. +This means that when you create an interface that extends a class with private or protected members, that interface type can only be implemented by that class or a subclass of it. + +This is useful when you have a large inheritance hierarchy, but want to specify that your code works with only subclasses that have certain properties. +The subclasses don't have to be related besides inheriting from the base class. +For example: + +```ts twoslash +// @errors: 2300 2420 2300 +class Control { + private state: any; +} + +interface SelectableControl extends Control { + select(): void; +} + +class Button extends Control implements SelectableControl { + select() {} +} + +class TextBox extends Control { + select() {} +} + +class ImageControl implements SelectableControl { + private state: any; + select() {} +} +``` + +In the above example, `SelectableControl` contains all of the members of `Control`, including the private `state` property. +Since `state` is a private member it is only possible for descendants of `Control` to implement `SelectableControl`. +This is because only descendants of `Control` will have a `state` private member that originates in the same declaration, which is a requirement for private members to be compatible. + +Within the `Control` class it is possible to access the `state` private member through an instance of `SelectableControl`. +Effectively, a `SelectableControl` acts like a `Control` that is known to have a `select` method. +The `Button` and `TextBox` classes are subtypes of `SelectableControl` (because they both inherit from `Control` and have a `select` method). The `ImageControl` class has its own `state` private member rather than extending `Control`, so it cannot implement `SelectableControl`. diff --git a/docs/documentation/zh/handbook-v1/Literal Types.md b/docs/documentation/zh/handbook-v1/Literal Types.md new file mode 100644 index 00000000..5925d248 --- /dev/null +++ b/docs/documentation/zh/handbook-v1/Literal Types.md @@ -0,0 +1,120 @@ +--- +title: Literal Types +layout: docs +permalink: /docs/handbook/literal-types.html +oneline: Using literal types with TypeScript +handbook: "true" +deprecated_by: /docs/handbook/2/everyday-types.html#literal-types +--- + +A literal is a more concrete sub-type of a collective type. +What this means is that `"Hello World"` is a `string`, but a `string` is not `"Hello World"` inside the type system. + +There are three sets of literal types available in TypeScript today: strings, numbers, and booleans; by using literal types you can allow an exact value which a string, number, or boolean must have. + +## Literal Narrowing + +When you declare a variable via `var` or `let`, you are telling the compiler that there is the chance that this variable will change its contents. +In contrast, using `const` to declare a variable will inform TypeScript that this object will never change. + +```ts twoslash +// We're making a guarantee that this variable +// helloWorld will never change, by using const. + +// So, TypeScript sets the type to be "Hello World", not string +const helloWorld = "Hello World"; + +// On the other hand, a let can change, and so the compiler declares it a string +let hiWorld = "Hi World"; +``` + +The process of going from an infinite number of potential cases (there are an infinite number of possible string values) to a smaller, finite number of potential case (in `helloWorld`'s case: 1) is called narrowing. + +## String Literal Types + +In practice string literal types combine nicely with union types, type guards, and type aliases. +You can use these features together to get enum-like behavior with strings. + +```ts twoslash +// @errors: 2345 +type Easing = "ease-in" | "ease-out" | "ease-in-out"; + +class UIElement { + animate(dx: number, dy: number, easing: Easing) { + if (easing === "ease-in") { + // ... + } else if (easing === "ease-out") { + } else if (easing === "ease-in-out") { + } else { + // It's possible that someone could reach this + // by ignoring your types though. + } + } +} + +let button = new UIElement(); +button.animate(0, 0, "ease-in"); +button.animate(0, 0, "uneasy"); +``` + +You can pass any of the three allowed strings, but any other string will give the error + +``` +Argument of type '"uneasy"' is not assignable to parameter of type '"ease-in" | "ease-out" | "ease-in-out"' +``` + +String literal types can be used in the same way to distinguish overloads: + +```ts +function createElement(tagName: "img"): HTMLImageElement; +function createElement(tagName: "input"): HTMLInputElement; +// ... more overloads ... +function createElement(tagName: string): Element { + // ... code goes here ... +} +``` + +## Numeric Literal Types + +TypeScript also has numeric literal types, which act the same as the string literals above. + +```ts twoslash +function rollDice(): 1 | 2 | 3 | 4 | 5 | 6 { + return (Math.floor(Math.random() * 6) + 1) as 1 | 2 | 3 | 4 | 5 | 6; +} + +const result = rollDice(); +``` + +A common case for their use is for describing config values: + +```ts twoslash +/** Creates a map centered at loc/lat */ +declare function setupMap(config: MapConfig): void; +// ---cut--- +interface MapConfig { + lng: number; + lat: number; + tileSize: 8 | 16 | 32; +} + +setupMap({ lng: -73.935242, lat: 40.73061, tileSize: 16 }); +``` + +## Boolean Literal Types + +TypeScript also has boolean literal types. You might use these to constrain object values whose properties are interrelated. + +```ts twoslash +interface ValidationSuccess { + isValid: true; + reason: null; +} + +interface ValidationFailure { + isValid: false; + reason: string; +} + +type ValidationResult = ValidationSuccess | ValidationFailure; +``` diff --git a/docs/documentation/zh/handbook-v1/Unions and Intersections.md b/docs/documentation/zh/handbook-v1/Unions and Intersections.md new file mode 100644 index 00000000..2246dd0a --- /dev/null +++ b/docs/documentation/zh/handbook-v1/Unions and Intersections.md @@ -0,0 +1,412 @@ +--- +title: Unions and Intersection Types +layout: docs +permalink: /docs/handbook/unions-and-intersections.html +oneline: How to use unions and intersection types in TypeScript +handbook: "true" +deprecated_by: /docs/handbook/2/everyday-types.html#union-types +# prettier-ignore +deprecation_redirects: [ + discriminating-unions, /docs/handbook/2/narrowing.html#discriminated-unions +] +--- + +So far, the handbook has covered types which are atomic objects. +However, as you model more types you find yourself looking for tools which let you compose or combine existing types instead of creating them from scratch. + +Intersection and Union types are one of the ways in which you can compose types. + +## Union Types + +Occasionally, you'll run into a library that expects a parameter to be either a `number` or a `string`. +For instance, take the following function: + +```ts twoslash +/** + * Takes a string and adds "padding" to the left. + * If 'padding' is a string, then 'padding' is appended to the left side. + * If 'padding' is a number, then that number of spaces is added to the left side. + */ +function padLeft(value: string, padding: any) { + if (typeof padding === "number") { + return Array(padding + 1).join(" ") + value; + } + if (typeof padding === "string") { + return padding + value; + } + throw new Error(`Expected string or number, got '${typeof padding}'.`); +} + +padLeft("Hello world", 4); // returns " Hello world" +``` + +The problem with `padLeft` in the above example is that its `padding` parameter is typed as `any`. +That means that we can call it with an argument that's neither a `number` nor a `string`, but TypeScript will be okay with it. + +```ts twoslash +declare function padLeft(value: string, padding: any): string; +// ---cut--- +// passes at compile time, fails at runtime. +let indentedString = padLeft("Hello world", true); +``` + +In traditional object-oriented code, we might abstract over the two types by creating a hierarchy of types. +While this is much more explicit, it's also a little bit overkill. +One of the nice things about the original version of `padLeft` was that we were able to just pass in primitives. +That meant that usage was simple and concise. +This new approach also wouldn't help if we were just trying to use a function that already exists elsewhere. + +Instead of `any`, we can use a _union type_ for the `padding` parameter: + +```ts twoslash +// @errors: 2345 +/** + * Takes a string and adds "padding" to the left. + * If 'padding' is a string, then 'padding' is appended to the left side. + * If 'padding' is a number, then that number of spaces is added to the left side. + */ +function padLeft(value: string, padding: string | number) { + // ... +} + +let indentedString = padLeft("Hello world", true); +``` + +A union type describes a value that can be one of several types. +We use the vertical bar (`|`) to separate each type, so `number | string | boolean` is the type of a value that can be a `number`, a `string`, or a `boolean`. + +## Unions with Common Fields + +If we have a value that is a union type, we can only access members that are common to all types in the union. + +```ts twoslash +// @errors: 2339 + +interface Bird { + fly(): void; + layEggs(): void; +} + +interface Fish { + swim(): void; + layEggs(): void; +} + +declare function getSmallPet(): Fish | Bird; + +let pet = getSmallPet(); +pet.layEggs(); + +// Only available in one of the two possible types +pet.swim(); +``` + +Union types can be a bit tricky here, but it just takes a bit of intuition to get used to. +If a value has the type `A | B`, we only know for _certain_ that it has members that both `A` _and_ `B` have. +In this example, `Bird` has a member named `fly`. +We can't be sure whether a variable typed as `Bird | Fish` has a `fly` method. +If the variable is really a `Fish` at runtime, then calling `pet.fly()` will fail. + +## Discriminating Unions + +A common technique for working with unions is to have a single field which uses literal types which you can use to let TypeScript narrow down the possible current type. For example, we're going to create a union of three types which have a single shared field. + +```ts +type NetworkLoadingState = { + state: "loading"; +}; + +type NetworkFailedState = { + state: "failed"; + code: number; +}; + +type NetworkSuccessState = { + state: "success"; + response: { + title: string; + duration: number; + summary: string; + }; +}; + +// Create a type which represents only one of the above types +// but you aren't sure which it is yet. +type NetworkState = + | NetworkLoadingState + | NetworkFailedState + | NetworkSuccessState; +``` + + + +All of the above types have a field named `state`, and then they also have their own fields: + + + + + + + + + + + + + + + + + + + +
NetworkLoadingStateNetworkFailedStateNetworkSuccessState
statestatestate
coderesponse
+ +Given the `state` field is common in every type inside `NetworkState` - it is safe for your code to access without an existence check. + +With `state` as a literal type, you can compare the value of `state` to the equivalent string and TypeScript will know which type is currently being used. + + + + + + + + + + + + + + +
NetworkLoadingStateNetworkFailedStateNetworkSuccessState
"loading""failed""success"
+ +In this case, you can use a `switch` statement to narrow down which type is represented at runtime: + +```ts twoslash +// @errors: 2339 +type NetworkLoadingState = { + state: "loading"; +}; + +type NetworkFailedState = { + state: "failed"; + code: number; +}; + +type NetworkSuccessState = { + state: "success"; + response: { + title: string; + duration: number; + summary: string; + }; +}; +// ---cut--- +type NetworkState = + | NetworkLoadingState + | NetworkFailedState + | NetworkSuccessState; + +function logger(state: NetworkState): string { + // Right now TypeScript does not know which of the three + // potential types state could be. + + // Trying to access a property which isn't shared + // across all types will raise an error + state.code; + + // By switching on state, TypeScript can narrow the union + // down in code flow analysis + switch (state.state) { + case "loading": + return "Downloading..."; + case "failed": + // The type must be NetworkFailedState here, + // so accessing the `code` field is safe + return `Error ${state.code} downloading`; + case "success": + return `Downloaded ${state.response.title} - ${state.response.summary}`; + } +} +``` + +## Union Exhaustiveness checking + +We would like the compiler to tell us when we don't cover all variants of the discriminated union. +For example, if we add `NetworkFromCachedState` to `NetworkState`, we need to update `logger` as well: + +```ts twoslash +// @errors: 2366 +type NetworkLoadingState = { state: "loading" }; +type NetworkFailedState = { state: "failed"; code: number }; +type NetworkSuccessState = { + state: "success"; + response: { + title: string; + duration: number; + summary: string; + }; +}; +// ---cut--- +type NetworkFromCachedState = { + state: "from_cache"; + id: string; + response: NetworkSuccessState["response"]; +}; + +type NetworkState = + | NetworkLoadingState + | NetworkFailedState + | NetworkSuccessState + | NetworkFromCachedState; + +function logger(s: NetworkState) { + switch (s.state) { + case "loading": + return "loading request"; + case "failed": + return `failed with code ${s.code}`; + case "success": + return "got response"; + } +} +``` + +There are two ways to do this. +The first is to turn on `--strictNullChecks` and specify a return type: + +```ts twoslash +// @errors: 2366 +type NetworkLoadingState = { state: "loading" }; +type NetworkFailedState = { state: "failed"; code: number }; +type NetworkSuccessState = { state: "success" }; +type NetworkFromCachedState = { state: "from_cache" }; + +type NetworkState = + | NetworkLoadingState + | NetworkFailedState + | NetworkSuccessState + | NetworkFromCachedState; + +// ---cut--- +function logger(s: NetworkState): string { + switch (s.state) { + case "loading": + return "loading request"; + case "failed": + return `failed with code ${s.code}`; + case "success": + return "got response"; + } +} +``` + +Because the `switch` is no longer exhaustive, TypeScript is aware that the function could sometimes return `undefined`. +If you have an explicit return type `string`, then you will get an error that the return type is actually `string | undefined`. +However, this method is quite subtle and, besides, [`--strictNullChecks`](/tsconfig#strictNullChecks) does not always work with old code. + +The second method uses the `never` type that the compiler uses to check for exhaustiveness: + +```ts twoslash +// @errors: 2345 +type NetworkLoadingState = { state: "loading" }; +type NetworkFailedState = { state: "failed"; code: number }; +type NetworkSuccessState = { state: "success" }; +type NetworkFromCachedState = { state: "from_cache" }; + +type NetworkState = + | NetworkLoadingState + | NetworkFailedState + | NetworkSuccessState + | NetworkFromCachedState; +// ---cut--- +function assertNever(x: never): never { + throw new Error("Unexpected object: " + x); +} + +function logger(s: NetworkState): string { + switch (s.state) { + case "loading": + return "loading request"; + case "failed": + return `failed with code ${s.code}`; + case "success": + return "got response"; + default: + return assertNever(s); + } +} +``` + +Here, `assertNever` checks that `s` is of type `never` — the type that's left after all other cases have been removed. +If you forget a case, then `s` will have a real type and you will get a type error. +This method requires you to define an extra function, but it's much more obvious when you forget it because the error message includes the missing type name. + +## Intersection Types + +Intersection types are closely related to union types, but they are used very differently. +An intersection type combines multiple types into one. +This allows you to add together existing types to get a single type that has all the features you need. +For example, `Person & Serializable & Loggable` is a type which is all of `Person` _and_ `Serializable` _and_ `Loggable`. +That means an object of this type will have all members of all three types. + +For example, if you had networking requests with consistent error handling then you could separate out the error handling into its own type which is merged with types which correspond to a single response type. + +```ts twoslash +interface ErrorHandling { + success: boolean; + error?: { message: string }; +} + +interface ArtworksData { + artworks: { title: string }[]; +} + +interface ArtistsData { + artists: { name: string }[]; +} + +// These interfaces are composed to have +// consistent error handling, and their own data. + +type ArtworksResponse = ArtworksData & ErrorHandling; +type ArtistsResponse = ArtistsData & ErrorHandling; + +const handleArtistsResponse = (response: ArtistsResponse) => { + if (response.error) { + console.error(response.error.message); + return; + } + + console.log(response.artists); +}; +``` diff --git a/docs/documentation/zh/handbook-v2/Basics.md b/docs/documentation/zh/handbook-v2/Basics.md new file mode 100644 index 00000000..c7435c94 --- /dev/null +++ b/docs/documentation/zh/handbook-v2/Basics.md @@ -0,0 +1,440 @@ +--- +title: The Basics +layout: docs +permalink: /docs/handbook/2/basic-types.html +oneline: "Step one in learning TypeScript: The basic types." +preamble: > +

Welcome to the first page of the handbook, if this is your first experience with TypeScript - you may want to start at one of the 'Getting Started' guides +--- + +Each and every value in JavaScript has a set of behaviors you can observe from running different operations. +That sounds abstract, but as a quick example, consider some operations we might run on a variable named `message`. + +```js +// Accessing the property 'toLowerCase' +// on 'message' and then calling it +message.toLowerCase(); + +// Calling 'message' +message(); +``` + +If we break this down, the first runnable line of code accesses a property called `toLowerCase` and then calls it. +The second one tries to call `message` directly. + +But assuming we don't know the value of `message` - and that's pretty common - we can't reliably say what results we'll get from trying to run any of this code. +The behavior of each operation depends entirely on what value we had in the first place. + +- Is `message` callable? +- Does it have a property called `toLowerCase` on it? +- If it does, is `toLowerCase` even callable? +- If both of these values are callable, what do they return? + +The answers to these questions are usually things we keep in our heads when we write JavaScript, and we have to hope we got all the details right. + +Let's say `message` was defined in the following way. + +```js +const message = "Hello World!"; +``` + +As you can probably guess, if we try to run `message.toLowerCase()`, we'll get the same string only in lower-case. + +What about that second line of code? +If you're familiar with JavaScript, you'll know this fails with an exception: + +```txt +TypeError: message is not a function +``` + +It'd be great if we could avoid mistakes like this. + +When we run our code, the way that our JavaScript runtime chooses what to do is by figuring out the _type_ of the value - what sorts of behaviors and capabilities it has. +That's part of what that `TypeError` is alluding to - it's saying that the string `"Hello World!"` cannot be called as a function. + +For some values, such as the primitives `string` and `number`, we can identify their type at runtime using the `typeof` operator. +But for other things like functions, there's no corresponding runtime mechanism to identify their types. +For example, consider this function: + +```js +function fn(x) { + return x.flip(); +} +``` + +We can _observe_ by reading the code that this function will only work if given an object with a callable `flip` property, but JavaScript doesn't surface this information in a way that we can check while the code is running. +The only way in pure JavaScript to tell what `fn` does with a particular value is to call it and see what happens. +This kind of behavior makes it hard to predict what code will do before it runs, which means it's harder to know what your code is going to do while you're writing it. + +Seen in this way, a _type_ is the concept of describing which values can be passed to `fn` and which will crash. +JavaScript only truly provides _dynamic_ typing - running the code to see what happens. + +The alternative is to use a _static_ type system to make predictions about what code is expected _before_ it runs. + +## Static type-checking + +Think back to that `TypeError` we got earlier from trying to call a `string` as a function. +_Most people_ don't like to get any sorts of errors when running their code - those are considered bugs! +And when we write new code, we try our best to avoid introducing new bugs. + +If we add just a bit of code, save our file, re-run the code, and immediately see the error, we might be able to isolate the problem quickly; but that's not always the case. +We might not have tested the feature thoroughly enough, so we might never actually run into a potential error that would be thrown! +Or if we were lucky enough to witness the error, we might have ended up doing large refactorings and adding a lot of different code that we're forced to dig through. + +Ideally, we could have a tool that helps us find these bugs _before_ our code runs. +That's what a static type-checker like TypeScript does. +_Static types systems_ describe the shapes and behaviors of what our values will be when we run our programs. +A type-checker like TypeScript uses that information and tells us when things might be going off the rails. + +```ts twoslash +// @errors: 2349 +const message = "hello!"; + +message(); +``` + +Running that last sample with TypeScript will give us an error message before we run the code in the first place. + +## Non-exception Failures + +So far we've been discussing certain things like runtime errors - cases where the JavaScript runtime tells us that it thinks something is nonsensical. +Those cases come up because [the ECMAScript specification](https://tc39.github.io/ecma262/) has explicit instructions on how the language should behave when it runs into something unexpected. + +For example, the specification says that trying to call something that isn't callable should throw an error. +Maybe that sounds like "obvious behavior", but you could imagine that accessing a property that doesn't exist on an object should throw an error too. +Instead, JavaScript gives us different behavior and returns the value `undefined`: + +```js +const user = { + name: "Daniel", + age: 26, +}; + +user.location; // returns undefined +``` + +Ultimately, a static type system has to make the call over what code should be flagged as an error in its system, even if it's "valid" JavaScript that won't immediately throw an error. +In TypeScript, the following code produces an error about `location` not being defined: + +```ts twoslash +// @errors: 2339 +const user = { + name: "Daniel", + age: 26, +}; + +user.location; +``` + +While sometimes that implies a trade-off in what you can express, the intent is to catch legitimate bugs in our programs. +And TypeScript catches _a lot_ of legitimate bugs. + +For example: typos, + +```ts twoslash +// @noErrors +const announcement = "Hello World!"; + +// How quickly can you spot the typos? +announcement.toLocaleLowercase(); +announcement.toLocalLowerCase(); + +// We probably meant to write this... +announcement.toLocaleLowerCase(); +``` + +uncalled functions, + +```ts twoslash +// @noUnusedLocals +// @errors: 2365 +function flipCoin() { + // Meant to be Math.random() + return Math.random < 0.5; +} +``` + +or basic logic errors. + +```ts twoslash +// @errors: 2367 +const value = Math.random() < 0.5 ? "a" : "b"; +if (value !== "a") { + // ... +} else if (value === "b") { + // Oops, unreachable +} +``` + +## Types for Tooling + +TypeScript can catch bugs when we make mistakes in our code. +That's great, but TypeScript can _also_ prevent us from making those mistakes in the first place. + +The type-checker has information to check things like whether we're accessing the right properties on variables and other properties. +Once it has that information, it can also start _suggesting_ which properties you might want to use. + +That means TypeScript can be leveraged for editing code too, and the core type-checker can provide error messages and code completion as you type in the editor. +That's part of what people often refer to when they talk about tooling in TypeScript. + + +```ts twoslash +// @noErrors +// @esModuleInterop +import express from "express"; +const app = express(); + +app.get("/", function (req, res) { + res.sen +// ^| +}); + +app.listen(3000); +``` + +TypeScript takes tooling seriously, and that goes beyond completions and errors as you type. +An editor that supports TypeScript can deliver "quick fixes" to automatically fix errors, refactorings to easily re-organize code, and useful navigation features for jumping to definitions of a variable, or finding all references to a given variable. +All of this is built on top of the type-checker and is fully cross-platform, so it's likely that [your favorite editor has TypeScript support available](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support). + +## `tsc`, the TypeScript compiler + +We've been talking about type-checking, but we haven't yet used our type-_checker_. +Let's get acquainted with our new friend `tsc`, the TypeScript compiler. +First we'll need to grab it via npm. + +```sh +npm install -g typescript +``` + +> This installs the TypeScript Compiler `tsc` globally. +> You can use `npx` or similar tools if you'd prefer to run `tsc` from a local `node_modules` package instead. + +Now let's move to an empty folder and try writing our first TypeScript program: `hello.ts`: + +```ts twoslash +// Greets the world. +console.log("Hello world!"); +``` + +Notice there are no frills here; this "hello world" program looks identical to what you'd write for a "hello world" program in JavaScript. +And now let's type-check it by running the command `tsc` which was installed for us by the `typescript` package. + +```sh +tsc hello.ts +``` + +Tada! + +Wait, "tada" _what_ exactly? +We ran `tsc` and nothing happened! +Well, there were no type errors, so we didn't get any output in our console since there was nothing to report. + +But check again - we got some _file_ output instead. +If we look in our current directory, we'll see a `hello.js` file next to `hello.ts`. +That's the output from our `hello.ts` file after `tsc` _compiles_ or _transforms_ it into a plain JavaScript file. +And if we check the contents, we'll see what TypeScript spits out after it processes a `.ts` file: + +```js +// Greets the world. +console.log("Hello world!"); +``` + +In this case, there was very little for TypeScript to transform, so it looks identical to what we wrote. +The compiler tries to emit clean readable code that looks like something a person would write. +While that's not always so easy, TypeScript indents consistently, is mindful of when our code spans across different lines of code, and tries to keep comments around. + +What about if we _did_ introduce a type-checking error? +Let's rewrite `hello.ts`: + +```ts twoslash +// @noErrors +// This is an industrial-grade general-purpose greeter function: +function greet(person, date) { + console.log(`Hello ${person}, today is ${date}!`); +} + +greet("Brendan"); +``` + +If we run `tsc hello.ts` again, notice that we get an error on the command line! + +```txt +Expected 2 arguments, but got 1. +``` + +TypeScript is telling us we forgot to pass an argument to the `greet` function, and rightfully so. +So far we've only written standard JavaScript, and yet type-checking was still able to find problems with our code. +Thanks TypeScript! + +## Emitting with Errors + +One thing you might not have noticed from the last example was that our `hello.js` file changed again. +If we open that file up then we'll see that the contents still basically look the same as our input file. +That might be a bit surprising given the fact that `tsc` reported an error about our code, but this is based on one of TypeScript's core values: much of the time, _you_ will know better than TypeScript. + +To reiterate from earlier, type-checking code limits the sorts of programs you can run, and so there's a tradeoff on what sorts of things a type-checker finds acceptable. +Most of the time that's okay, but there are scenarios where those checks get in the way. +For example, imagine yourself migrating JavaScript code over to TypeScript and introducing type-checking errors. +Eventually you'll get around to cleaning things up for the type-checker, but that original JavaScript code was already working! +Why should converting it over to TypeScript stop you from running it? + +So TypeScript doesn't get in your way. +Of course, over time, you may want to be a bit more defensive against mistakes, and make TypeScript act a bit more strictly. +In that case, you can use the `--noEmitOnError` compiler option. +Try changing your `hello.ts` file and running `tsc` with that flag: + +```sh +tsc --noEmitOnError hello.ts +``` + +You'll notice that `hello.js` never gets updated. + +## Explicit Types + +Up until now, we haven't told TypeScript what `person` or `date` are. +Let's edit the code to tell TypeScript that `person` is a `string`, and that `date` should be a `Date` object. +We'll also use the `toDateString()` method on `date`. + +```ts twoslash +function greet(person: string, date: Date) { + console.log(`Hello ${person}, today is ${date.toDateString()}!`); +} +``` + +What we did was add _type annotations_ on `person` and `date` to describe what types of values `greet` can be called with. +You can read that signature as "`greet` takes a `person` of type `string`, and a `date` of type `Date`". + +With this, TypeScript can tell us about other cases where we might have been called incorrectly. +For example... + +```ts twoslash +// @errors: 2345 +function greet(person: string, date: Date) { + console.log(`Hello ${person}, today is ${date.toDateString()}!`); +} + +greet("Maddison", Date()); +``` + +Huh? +TypeScript reported an error on our second argument, but why? + +Perhaps surprisingly, calling `Date()` in JavaScript returns a `string`. +On the other hand, constructing a `Date` with `new Date()` actually gives us what we were expecting. + +Anyway, we can quickly fix up the error: + +```ts twoslash {4} +function greet(person: string, date: Date) { + console.log(`Hello ${person}, today is ${date.toDateString()}!`); +} + +greet("Maddison", new Date()); +``` + +Keep in mind, we don't always have to write explicit type annotations. +In many cases, TypeScript can even just _infer_ (or "figure out") the types for us even if we omit them. + +```ts twoslash +let msg = "hello there!"; +// ^? +``` + +Even though we didn't tell TypeScript that `msg` had the type `string` it was able to figure that out. +That's a feature, and it's best not to add annotations when the type system would end up inferring the same type anyway. + +> Note: the message bubble inside the code sample above. That is what your editor would show if you had hovered over the word. + +## Erased Types + +Let's take a look at what happens when we compile the above function `greet` with `tsc` to output JavaScript: + +```ts twoslash +// @showEmit +// @target: es5 +function greet(person: string, date: Date) { + console.log(`Hello ${person}, today is ${date.toDateString()}!`); +} + +greet("Maddison", new Date()); +``` + +Notice two things here: + +1. Our `person` and `date` parameters no longer have type annotations. +2. Our "template string" - that string that used backticks (the `` ` `` character) - was converted to plain strings with concatenations (`+`). + +More on that second point later, but let's now focus on that first point. +Type annotations aren't part of JavaScript (or ECMAScript to be pedantic), so there really aren't any browsers or other runtimes that can just run TypeScript unmodified. +That's why TypeScript needs a compiler in the first place - it needs some way to strip out or transform any TypeScript-specific code so that you can run it. +Most TypeScript-specific code gets erased away, and likewise, here our type annotations were completely erased. + +> **Remember**: Type annotations never change the runtime behavior of your program. + +## Downleveling + +One other difference from the above was that our template string was rewritten from + +```js +`Hello ${person}, today is ${date.toDateString()}!`; +``` + +to + +```js +"Hello " + person + ", today is " + date.toDateString() + "!"; +``` + +Why did this happen? + +Template strings are a feature from a version of ECMAScript called ECMAScript 2015 (a.k.a. ECMAScript 6, ES2015, ES6, etc. - _don't ask_). +TypeScript has the ability to rewrite code from newer versions of ECMAScript to older ones such as ECMAScript 3 or ECMAScript 5 (a.k.a. ES3 and ES5). +This process of moving from a newer or "higher" version of ECMAScript down to an older or "lower" one is sometimes called _downleveling_. + +By default TypeScript targets ES3, an extremely old version of ECMAScript. +We could have chosen something a little bit more recent by using the `--target` flag. +Running with `--target es2015` changes TypeScript to target ECMAScript 2015, meaning code should be able to run wherever ECMAScript 2015 is supported. +So running `tsc --target es2015 hello.ts` gives us the following output: + +```js +function greet(person, date) { + console.log(`Hello ${person}, today is ${date.toDateString()}!`); +} +greet("Maddison", new Date()); +``` + +> While the default target is ES3, the great majority of current browsers support ES2015. +> Most developers can therefore safely specify ES2015 or above as a target, unless compatibility with certain ancient browsers is important. + +## Strictness + +Different users come to TypeScript looking for different things in a type-checker. +Some people are looking for a more loose opt-in experience which can help validate only some parts of their program, and still have decent tooling. +This is the default experience with TypeScript, where types are optional, inference takes the most lenient types, and there's no checking for potentially `null`/`undefined` values. +Much like how `tsc` emits in the face of errors, these defaults are put in place to stay out of your way. +If you're migrating existing JavaScript, that might be a desirable first step. + +In contrast, a lot of users prefer to have TypeScript validate as much as it can straight away, and that's why the language provides strictness settings as well. +These strictness settings turn static type-checking from a switch (either your code is checked or not) into something closer to a dial. +The further you turn this dial up, the more TypeScript will check for you. +This can require a little extra work, but generally speaking it pays for itself in the long run, and enables more thorough checks and more accurate tooling. +When possible, a new codebase should always turn these strictness checks on. + +TypeScript has several type-checking strictness flags that can be turned on or off, and all of our examples will be written with all of them enabled unless otherwise stated. +The `--strict` flag in the CLI, or `"strict": true` in a [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) toggles them all on simultaneously, but we can opt out of them individually. +The two biggest ones you should know about are `noImplicitAny` and `strictNullChecks`. + +## `noImplicitAny` + +Recall that in some places, TypeScript doesn't try to infer any types for us and instead falls back to the most lenient type: `any`. +This isn't the worst thing that can happen - after all, falling back to `any` is just the plain JavaScript experience anyway. + +However, using `any` often defeats the purpose of using TypeScript in the first place. +The more typed your program is, the more validation and tooling you'll get, meaning you'll run into fewer bugs as you code. +Turning on the `noImplicitAny` flag will issue an error on any variables whose type is implicitly inferred as `any`. + +## `strictNullChecks` + +By default, values like `null` and `undefined` are assignable to any other type. +This can make writing some code easier, but forgetting to handle `null` and `undefined` is the cause of countless bugs in the world - some consider it a [billion dollar mistake](https://www.youtube.com/watch?v=ybrQvs4x0Ps)! +The `strictNullChecks` flag makes handling `null` and `undefined` more explicit, and _spares_ us from worrying about whether we _forgot_ to handle `null` and `undefined`. diff --git a/docs/documentation/zh/handbook-v2/Classes.md b/docs/documentation/zh/handbook-v2/Classes.md new file mode 100644 index 00000000..46ce7800 --- /dev/null +++ b/docs/documentation/zh/handbook-v2/Classes.md @@ -0,0 +1,1414 @@ +--- +title: Classes +layout: docs +permalink: /docs/handbook/2/classes.html +oneline: "How classes work in TypeScript" +--- + +

+

Background Reading:
Classes (MDN)

+
+ +TypeScript offers full support for the `class` keyword introduced in ES2015. + +As with other JavaScript language features, TypeScript adds type annotations and other syntax to allow you to express relationships between classes and other types. + +## Class Members + +Here's the most basic class - an empty one: + +```ts twoslash +class Point {} +``` + +This class isn't very useful yet, so let's start adding some members. + +### Fields + +A field declaration creates a public writeable property on a class: + +```ts twoslash +// @strictPropertyInitialization: false +class Point { + x: number; + y: number; +} + +const pt = new Point(); +pt.x = 0; +pt.y = 0; +``` + +As with other locations, the type annotation is optional, but will be an implicit `any` if not specified. + +Fields can also have _initializers_; these will run automatically when the class is instantiated: + +```ts twoslash +class Point { + x = 0; + y = 0; +} + +const pt = new Point(); +// Prints 0, 0 +console.log(`${pt.x}, ${pt.y}`); +``` + +Just like with `const`, `let`, and `var`, the initializer of a class property will be used to infer its type: + +```ts twoslash +// @errors: 2322 +class Point { + x = 0; + y = 0; +} +// ---cut--- +const pt = new Point(); +pt.x = "0"; +``` + +#### `--strictPropertyInitialization` + +The `strictPropertyInitialization` setting controls whether class fields need to be initialized in the constructor. + +```ts twoslash +// @errors: 2564 +class BadGreeter { + name: string; +} +``` + +```ts twoslash +class GoodGreeter { + name: string; + + constructor() { + this.name = "hello"; + } +} +``` + +Note that the field needs to be initialized _in the constructor itself_. +TypeScript does not analyze methods you invoke from the constructor to detect initializations, because a derived class might override those methods and fail to initialize the members. + +If you intend to definitely initialize a field through means other than the constructor (for example, maybe an external library is filling in part of your class for you), you can use the _definite assignment assertion operator_, `!`: + +```ts twoslash +class OKGreeter { + // Not initialized, but no error + name!: string; +} +``` + +### `readonly` + +Fields may be prefixed with the `readonly` modifier. +This prevents assignments to the field outside of the constructor. + +```ts twoslash +// @errors: 2540 2540 +class Greeter { + readonly name: string = "world"; + + constructor(otherName?: string) { + if (otherName !== undefined) { + this.name = otherName; + } + } + + err() { + this.name = "not ok"; + } +} +const g = new Greeter(); +g.name = "also not ok"; +``` + +### Constructors + +
+

Background Reading:
+ Constructor (MDN)
+

+
+ +Class constructors are very similar to functions. +You can add parameters with type annotations, default values, and overloads: + +```ts twoslash +class Point { + x: number; + y: number; + + // Normal signature with defaults + constructor(x = 0, y = 0) { + this.x = x; + this.y = y; + } +} +``` + +```ts twoslash +class Point { + // Overloads + constructor(x: number, y: string); + constructor(s: string); + constructor(xs: any, y?: any) { + // TBD + } +} +``` + +There are just a few differences between class constructor signatures and function signatures: + +- Constructors can't have type parameters - these belong on the outer class declaration, which we'll learn about later +- Constructors can't have return type annotations - the class instance type is always what's returned + +#### Super Calls + +Just as in JavaScript, if you have a base class, you'll need to call `super();` in your constructor body before using any `this.` members: + +```ts twoslash +// @errors: 17009 +class Base { + k = 4; +} + +class Derived extends Base { + constructor() { + // Prints a wrong value in ES5; throws exception in ES6 + console.log(this.k); + super(); + } +} +``` + +Forgetting to call `super` is an easy mistake to make in JavaScript, but TypeScript will tell you when it's necessary. + +### Methods + +
+

Background Reading:
+ Method definitions
+

+
+ +A function property on a class is called a _method_. +Methods can use all the same type annotations as functions and constructors: + +```ts twoslash +class Point { + x = 10; + y = 10; + + scale(n: number): void { + this.x *= n; + this.y *= n; + } +} +``` + +Other than the standard type annotations, TypeScript doesn't add anything else new to methods. + +Note that inside a method body, it is still mandatory to access fields and other methods via `this.`. +An unqualified name in a method body will always refer to something in the enclosing scope: + +```ts twoslash +// @errors: 2322 +let x: number = 0; + +class C { + x: string = "hello"; + + m() { + // This is trying to modify 'x' from line 1, not the class property + x = "world"; + } +} +``` + +### Getters / Setters + +Classes can also have _accessors_: + +```ts twoslash +class C { + _length = 0; + get length() { + return this._length; + } + set length(value) { + this._length = value; + } +} +``` + +> Note that a field-backed get/set pair with no extra logic is very rarely useful in JavaScript. +> It's fine to expose public fields if you don't need to add additional logic during the get/set operations. + +TypeScript has some special inference rules for accessors: + +- If `get` exists but no `set`, the property is automatically `readonly` +- If the type of the setter parameter is not specified, it is inferred from the return type of the getter +- Getters and setters must have the same [Member Visibility](#member-visibility) + +Since [TypeScript 4.3](https://devblogs.microsoft.com/typescript/announcing-typescript-4-3/), it is possible to have accessors with different types for getting and setting. + +```ts twoslash +class Thing { + _size = 0; + + get size(): number { + return this._size; + } + + set size(value: string | number | boolean) { + let num = Number(value); + + // Don't allow NaN, Infinity, etc + + if (!Number.isFinite(num)) { + this._size = 0; + return; + } + + this._size = num; + } +} +``` + +### Index Signatures + +Classes can declare index signatures; these work the same as [Index Signatures for other object types](/docs/handbook/2/objects.html#index-signatures): + +```ts twoslash +class MyClass { + [s: string]: boolean | ((s: string) => boolean); + + check(s: string) { + return this[s] as boolean; + } +} +``` + +Because the index signature type needs to also capture the types of methods, it's not easy to usefully use these types. +Generally it's better to store indexed data in another place instead of on the class instance itself. + +## Class Heritage + +Like other languages with object-oriented features, classes in JavaScript can inherit from base classes. + +### `implements` Clauses + +You can use an `implements` clause to check that a class satisfies a particular `interface`. +An error will be issued if a class fails to correctly implement it: + +```ts twoslash +// @errors: 2420 +interface Pingable { + ping(): void; +} + +class Sonar implements Pingable { + ping() { + console.log("ping!"); + } +} + +class Ball implements Pingable { + pong() { + console.log("pong!"); + } +} +``` + +Classes may also implement multiple interfaces, e.g. `class C implements A, B {`. + +#### Cautions + +It's important to understand that an `implements` clause is only a check that the class can be treated as the interface type. +It doesn't change the type of the class or its methods _at all_. +A common source of error is to assume that an `implements` clause will change the class type - it doesn't! + +```ts twoslash +// @errors: 7006 +interface Checkable { + check(name: string): boolean; +} + +class NameChecker implements Checkable { + check(s) { + // Notice no error here + return s.toLowercse() === "ok"; + // ^? + } +} +``` + +In this example, we perhaps expected that `s`'s type would be influenced by the `name: string` parameter of `check`. +It is not - `implements` clauses don't change how the class body is checked or its type inferred. + +Similarly, implementing an interface with an optional property doesn't create that property: + +```ts twoslash +// @errors: 2339 +interface A { + x: number; + y?: number; +} +class C implements A { + x = 0; +} +const c = new C(); +c.y = 10; +``` + +### `extends` Clauses + +
+

Background Reading:
+ extends keyword (MDN)
+

+
+ +Classes may `extend` from a base class. +A derived class has all the properties and methods of its base class, and also define additional members. + +```ts twoslash +class Animal { + move() { + console.log("Moving along!"); + } +} + +class Dog extends Animal { + woof(times: number) { + for (let i = 0; i < times; i++) { + console.log("woof!"); + } + } +} + +const d = new Dog(); +// Base class method +d.move(); +// Derived class method +d.woof(3); +``` + +#### Overriding Methods + +
+

Background Reading:
+ super keyword (MDN)
+

+
+ +A derived class can also override a base class field or property. +You can use the `super.` syntax to access base class methods. +Note that because JavaScript classes are a simple lookup object, there is no notion of a "super field". + +TypeScript enforces that a derived class is always a subtype of its base class. + +For example, here's a legal way to override a method: + +```ts twoslash +class Base { + greet() { + console.log("Hello, world!"); + } +} + +class Derived extends Base { + greet(name?: string) { + if (name === undefined) { + super.greet(); + } else { + console.log(`Hello, ${name.toUpperCase()}`); + } + } +} + +const d = new Derived(); +d.greet(); +d.greet("reader"); +``` + +It's important that a derived class follow its base class contract. +Remember that it's very common (and always legal!) to refer to a derived class instance through a base class reference: + +```ts twoslash +class Base { + greet() { + console.log("Hello, world!"); + } +} +declare const d: Base; +// ---cut--- +// Alias the derived instance through a base class reference +const b: Base = d; +// No problem +b.greet(); +``` + +What if `Derived` didn't follow `Base`'s contract? + +```ts twoslash +// @errors: 2416 +class Base { + greet() { + console.log("Hello, world!"); + } +} + +class Derived extends Base { + // Make this parameter required + greet(name: string) { + console.log(`Hello, ${name.toUpperCase()}`); + } +} +``` + +If we compiled this code despite the error, this sample would then crash: + +```ts twoslash +declare class Base { + greet(): void; +} +declare class Derived extends Base {} +// ---cut--- +const b: Base = new Derived(); +// Crashes because "name" will be undefined +b.greet(); +``` + +#### Initialization Order + +The order that JavaScript classes initialize can be surprising in some cases. +Let's consider this code: + +```ts twoslash +class Base { + name = "base"; + constructor() { + console.log("My name is " + this.name); + } +} + +class Derived extends Base { + name = "derived"; +} + +// Prints "base", not "derived" +const d = new Derived(); +``` + +What happened here? + +The order of class initialization, as defined by JavaScript, is: + +- The base class fields are initialized +- The base class constructor runs +- The derived class fields are initialized +- The derived class constructor runs + +This means that the base class constructor saw its own value for `name` during its own constructor, because the derived class field initializations hadn't run yet. + +#### Inheriting Built-in Types + +> Note: If you don't plan to inherit from built-in types like `Array`, `Error`, `Map`, etc. or your compilation target is explicitely set to `ES6`/`ES2015` or above, you may skip this section + +In ES2015, constructors which return an object implicitly substitute the value of `this` for any callers of `super(...)`. +It is necessary for generated constructor code to capture any potential return value of `super(...)` and replace it with `this`. + +As a result, subclassing `Error`, `Array`, and others may no longer work as expected. +This is due to the fact that constructor functions for `Error`, `Array`, and the like use ECMAScript 6's `new.target` to adjust the prototype chain; +however, there is no way to ensure a value for `new.target` when invoking a constructor in ECMAScript 5. +Other downlevel compilers generally have the same limitation by default. + +For a subclass like the following: + +```ts twoslash +class MsgError extends Error { + constructor(m: string) { + super(m); + } + sayHello() { + return "hello " + this.message; + } +} +``` + +you may find that: + +- methods may be `undefined` on objects returned by constructing these subclasses, so calling `sayHello` will result in an error. +- `instanceof` will be broken between instances of the subclass and their instances, so `(new MsgError()) instanceof MsgError` will return `false`. + +As a recommendation, you can manually adjust the prototype immediately after any `super(...)` calls. + +```ts twoslash +class MsgError extends Error { + constructor(m: string) { + super(m); + + // Set the prototype explicitly. + Object.setPrototypeOf(this, MsgError.prototype); + } + + sayHello() { + return "hello " + this.message; + } +} +``` + +However, any subclass of `MsgError` will have to manually set the prototype as well. +For runtimes that don't support [`Object.setPrototypeOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf), you may instead be able to use [`__proto__`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto). + +Unfortunately, [these workarounds will not work on Internet Explorer 10 and prior](). +One can manually copy methods from the prototype onto the instance itself (i.e. `MsgError.prototype` onto `this`), but the prototype chain itself cannot be fixed. + +## Member Visibility + +You can use TypeScript to control whether certain methods or properties are visible to code outside the class. + +### `public` + +The default visibility of class members is `public`. +A `public` member can be accessed anywhere: + +```ts twoslash +class Greeter { + public greet() { + console.log("hi!"); + } +} +const g = new Greeter(); +g.greet(); +``` + +Because `public` is already the default visibility modifier, you don't ever _need_ to write it on a class member, but might choose to do so for style/readability reasons. + +### `protected` + +`protected` members are only visible to subclasses of the class they're declared in. + +```ts twoslash +// @errors: 2445 +class Greeter { + public greet() { + console.log("Hello, " + this.getName()); + } + protected getName() { + return "hi"; + } +} + +class SpecialGreeter extends Greeter { + public howdy() { + // OK to access protected member here + console.log("Howdy, " + this.getName()); + // ^^^^^^^^^^^^^^ + } +} +const g = new SpecialGreeter(); +g.greet(); // OK +g.getName(); +``` + +#### Exposure of `protected` members + +Derived classes need to follow their base class contracts, but may choose to expose a subtype of base class with more capabilities. +This includes making `protected` members `public`: + +```ts twoslash +class Base { + protected m = 10; +} +class Derived extends Base { + // No modifier, so default is 'public' + m = 15; +} +const d = new Derived(); +console.log(d.m); // OK +``` + +Note that `Derived` was already able to freely read and write `m`, so this doesn't meaningfully alter the "security" of this situation. +The main thing to note here is that in the derived class, we need to be careful to repeat the `protected` modifier if this exposure isn't intentional. + +#### Cross-hierarchy `protected` access + +Different OOP languages disagree about whether it's legal to access a `protected` member through a base class reference: + +```ts twoslash +// @errors: 2446 +class Base { + protected x: number = 1; +} +class Derived1 extends Base { + protected x: number = 5; +} +class Derived2 extends Base { + f1(other: Derived2) { + other.x = 10; + } + f2(other: Base) { + other.x = 10; + } +} +``` + +Java, for example, considers this to be legal. +On the other hand, C# and C++ chose that this code should be illegal. + +TypeScript sides with C# and C++ here, because accessing `x` in `Derived2` should only be legal from `Derived2`'s subclasses, and `Derived1` isn't one of them. +Moreover, if accessing `x` through a `Derived1` reference is illegal (which it certainly should be!), then accessing it through a base class reference should never improve the situation. + +See also [Why Can’t I Access A Protected Member From A Derived Class?](https://blogs.msdn.microsoft.com/ericlippert/2005/11/09/why-cant-i-access-a-protected-member-from-a-derived-class/) which explains more of C#'s reasoning. + +### `private` + +`private` is like `protected`, but doesn't allow access to the member even from subclasses: + +```ts twoslash +// @errors: 2341 +class Base { + private x = 0; +} +const b = new Base(); +// Can't access from outside the class +console.log(b.x); +``` + +```ts twoslash +// @errors: 2341 +class Base { + private x = 0; +} +// ---cut--- +class Derived extends Base { + showX() { + // Can't access in subclasses + console.log(this.x); + } +} +``` + +Because `private` members aren't visible to derived classes, a derived class can't increase its visibility: + +```ts twoslash +// @errors: 2415 +class Base { + private x = 0; +} +class Derived extends Base { + x = 1; +} +``` + +#### Cross-instance `private` access + +Different OOP languages disagree about whether different instances of the same class may access each others' `private` members. +While languages like Java, C#, C++, Swift, and PHP allow this, Ruby does not. + +TypeScript does allow cross-instance `private` access: + +```ts twoslash +class A { + private x = 10; + + public sameAs(other: A) { + // No error + return other.x === this.x; + } +} +``` + +#### Caveats + +Like other aspects of TypeScript's type system, `private` and `protected` [are only enforced during type checking](https://www.typescriptlang.org/play?removeComments=true&target=99&ts=4.3.4#code/PTAEGMBsEMGddAEQPYHNQBMCmVoCcsEAHPASwDdoAXLUAM1K0gwQFdZSA7dAKWkoDK4MkSoByBAGJQJLAwAeAWABQIUH0HDSoiTLKUaoUggAW+DHorUsAOlABJcQlhUy4KpACeoLJzrI8cCwMGxU1ABVPIiwhESpMZEJQTmR4lxFQaQxWMm4IZABbIlIYKlJkTlDlXHgkNFAAbxVQTIAjfABrAEEC5FZOeIBeUAAGAG5mmSw8WAroSFIqb2GAIjMiIk8VieVJ8Ar01ncAgAoASkaAXxVr3dUwGoQAYWpMHBgCYn1rekZmNg4eUi0Vi2icoBWJCsNBWoA6WE8AHcAiEwmBgTEtDovtDaMZQLM6PEoQZbA5wSk0q5SO4vD4-AEghZoJwLGYEIRwNBoqAzFRwCZCFUIlFMXECdSiAhId8YZgclx0PsiiVqOVOAAaUAFLAsxWgKiC35MFigfC0FKgSAVVDTSyk+W5dB4fplHVVR6gF7xJrKFotEk-HXIRE9PoDUDDcaTAPTWaceaLZYQlmoPBbHYx-KcQ7HPDnK43FQqfY5+IMDDISPJLCIuqoc47UsuUCofAME3Vzi1r3URvF5QV5A2STtPDdXqunZDgDaYlHnTDrrEAF0dm28B3mDZg6HJwN1+2-hg57ulwNV2NQGoZbjYfNrYiENBwEFaojFiZQK08C-4fFKTVCozWfTgfFgLkeT5AUqiAA). + +This means that JavaScript runtime constructs like `in` or simple property lookup can still access a `private` or `protected` member: + +```ts twoslash +class MySafe { + private secretKey = 12345; +} +``` + +```js +// In a JavaScript file... +const s = new MySafe(); +// Will print 12345 +console.log(s.secretKey); +``` + +`private` also allows access using bracket notation during type checking. This makes `private`-declared fields potentially easier to access for things like unit tests, with the drawback that these fields are _soft private_ and don't strictly enforce privacy. + +```ts twoslash +// @errors: 2341 +class MySafe { + private secretKey = 12345; +} + +const s = new MySafe(); + +// Not allowed during type checking +console.log(s.secretKey); + +// OK +console.log(s["secretKey"]); +``` + +Unlike TypeScripts's `private`, JavaScript's [private fields](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) (`#`) remain private after compilation and do not provide the previously mentioned escape hatches like bracket notation access, making them _hard private_. + +```ts twoslash +class Dog { + #barkAmount = 0; + personality = "happy"; + + constructor() {} +} +``` + +```ts twoslash +// @target: esnext +// @showEmit +class Dog { + #barkAmount = 0; + personality = "happy"; + + constructor() {} +} +``` + +When compiling to ES2021 or less, TypeScript will use WeakMaps in place of `#`. + +```ts twoslash +// @target: es2015 +// @showEmit +class Dog { + #barkAmount = 0; + personality = "happy"; + + constructor() {} +} +``` + +If you need to protect values in your class from malicious actors, you should use mechanisms that offer hard runtime privacy, such as closures, WeakMaps, or private fields. Note that these added privacy checks during runtime could affect performance. + +## Static Members + +
+

Background Reading:
+ Static Members (MDN)
+

+
+ +Classes may have `static` members. +These members aren't associated with a particular instance of the class. +They can be accessed through the class constructor object itself: + +```ts twoslash +class MyClass { + static x = 0; + static printX() { + console.log(MyClass.x); + } +} +console.log(MyClass.x); +MyClass.printX(); +``` + +Static members can also use the same `public`, `protected`, and `private` visibility modifiers: + +```ts twoslash +// @errors: 2341 +class MyClass { + private static x = 0; +} +console.log(MyClass.x); +``` + +Static members are also inherited: + +```ts twoslash +class Base { + static getGreeting() { + return "Hello world"; + } +} +class Derived extends Base { + myGreeting = Derived.getGreeting(); +} +``` + +### Special Static Names + +It's generally not safe/possible to overwrite properties from the `Function` prototype. +Because classes are themselves functions that can be invoked with `new`, certain `static` names can't be used. +Function properties like `name`, `length`, and `call` aren't valid to define as `static` members: + +```ts twoslash +// @errors: 2699 +class S { + static name = "S!"; +} +``` + +### Why No Static Classes? + +TypeScript (and JavaScript) don't have a construct called `static class` the same way C# and Java do. + +Those constructs _only_ exist because those languages force all data and functions to be inside a class; because that restriction doesn't exist in TypeScript, there's no need for them. +A class with only a single instance is typically just represented as a normal _object_ in JavaScript/TypeScript. + +For example, we don't need a "static class" syntax in TypeScript because a regular object (or even top-level function) will do the job just as well: + +```ts twoslash +// Unnecessary "static" class +class MyStaticClass { + static doSomething() {} +} + +// Preferred (alternative 1) +function doSomething() {} + +// Preferred (alternative 2) +const MyHelperObject = { + dosomething() {}, +}; +``` + +## `static` Blocks in Classes + +Static blocks allow you to write a sequence of statements with their own scope that can access private fields within the containing class. This means that we can write initialization code with all the capabilities of writing statements, no leakage of variables, and full access to our class's internals. + +```ts twoslash +declare function loadLastInstances(): any[] +// ---cut--- +class Foo { + static #count = 0; + + get count() { + return Foo.#count; + } + + static { + try { + const lastInstances = loadLastInstances(); + Foo.#count += lastInstances.length; + } + catch {} + } +} +``` + +## Generic Classes + +Classes, much like interfaces, can be generic. +When a generic class is instantiated with `new`, its type parameters are inferred the same way as in a function call: + +```ts twoslash +class Box { + contents: Type; + constructor(value: Type) { + this.contents = value; + } +} + +const b = new Box("hello!"); +// ^? +``` + +Classes can use generic constraints and defaults the same way as interfaces. + +### Type Parameters in Static Members + +This code isn't legal, and it may not be obvious why: + +```ts twoslash +// @errors: 2302 +class Box { + static defaultValue: Type; +} +``` + +Remember that types are always fully erased! +At runtime, there's only _one_ `Box.defaultValue` property slot. +This means that setting `Box.defaultValue` (if that were possible) would _also_ change `Box.defaultValue` - not good. +The `static` members of a generic class can never refer to the class's type parameters. + +## `this` at Runtime in Classes + +
+

Background Reading:
+ this keyword (MDN)
+

+
+ +It's important to remember that TypeScript doesn't change the runtime behavior of JavaScript, and that JavaScript is somewhat famous for having some peculiar runtime behaviors. + +JavaScript's handling of `this` is indeed unusual: + +```ts twoslash +class MyClass { + name = "MyClass"; + getName() { + return this.name; + } +} +const c = new MyClass(); +const obj = { + name: "obj", + getName: c.getName, +}; + +// Prints "obj", not "MyClass" +console.log(obj.getName()); +``` + +Long story short, by default, the value of `this` inside a function depends on _how the function was called_. +In this example, because the function was called through the `obj` reference, its value of `this` was `obj` rather than the class instance. + +This is rarely what you want to happen! +TypeScript provides some ways to mitigate or prevent this kind of error. + +### Arrow Functions + +
+

Background Reading:
+ Arrow functions (MDN)
+

+
+ +If you have a function that will often be called in a way that loses its `this` context, it can make sense to use an arrow function property instead of a method definition: + +```ts twoslash +class MyClass { + name = "MyClass"; + getName = () => { + return this.name; + }; +} +const c = new MyClass(); +const g = c.getName; +// Prints "MyClass" instead of crashing +console.log(g()); +``` + +This has some trade-offs: + +- The `this` value is guaranteed to be correct at runtime, even for code not checked with TypeScript +- This will use more memory, because each class instance will have its own copy of each function defined this way +- You can't use `super.getName` in a derived class, because there's no entry in the prototype chain to fetch the base class method from + +### `this` parameters + +In a method or function definition, an initial parameter named `this` has special meaning in TypeScript. +These parameters are erased during compilation: + +```ts twoslash +type SomeType = any; +// ---cut--- +// TypeScript input with 'this' parameter +function fn(this: SomeType, x: number) { + /* ... */ +} +``` + +```js +// JavaScript output +function fn(x) { + /* ... */ +} +``` + +TypeScript checks that calling a function with a `this` parameter is done so with a correct context. +Instead of using an arrow function, we can add a `this` parameter to method definitions to statically enforce that the method is called correctly: + +```ts twoslash +// @errors: 2684 +class MyClass { + name = "MyClass"; + getName(this: MyClass) { + return this.name; + } +} +const c = new MyClass(); +// OK +c.getName(); + +// Error, would crash +const g = c.getName; +console.log(g()); +``` + +This method takes the opposite trade-offs of the arrow function approach: + +- JavaScript callers might still use the class method incorrectly without realizing it +- Only one function per class definition gets allocated, rather than one per class instance +- Base method definitions can still be called via `super.` + +## `this` Types + +In classes, a special type called `this` refers _dynamically_ to the type of the current class. +Let's see how this is useful: + + +```ts twoslash +class Box { + contents: string = ""; + set(value: string) { +// ^? + this.contents = value; + return this; + } +} +``` + +Here, TypeScript inferred the return type of `set` to be `this`, rather than `Box`. +Now let's make a subclass of `Box`: + +```ts twoslash +class Box { + contents: string = ""; + set(value: string) { + this.contents = value; + return this; + } +} +// ---cut--- +class ClearableBox extends Box { + clear() { + this.contents = ""; + } +} + +const a = new ClearableBox(); +const b = a.set("hello"); +// ^? +``` + +You can also use `this` in a parameter type annotation: + +```ts twoslash +class Box { + content: string = ""; + sameAs(other: this) { + return other.content === this.content; + } +} +``` + +This is different from writing `other: Box` -- if you have a derived class, its `sameAs` method will now only accept other instances of that same derived class: + +```ts twoslash +// @errors: 2345 +class Box { + content: string = ""; + sameAs(other: this) { + return other.content === this.content; + } +} + +class DerivedBox extends Box { + otherContent: string = "?"; +} + +const base = new Box(); +const derived = new DerivedBox(); +derived.sameAs(base); +``` + +### `this`-based type guards + +You can use `this is Type` in the return position for methods in classes and interfaces. +When mixed with a type narrowing (e.g. `if` statements) the type of the target object would be narrowed to the specified `Type`. + + +```ts twoslash +// @strictPropertyInitialization: false +class FileSystemObject { + isFile(): this is FileRep { + return this instanceof FileRep; + } + isDirectory(): this is Directory { + return this instanceof Directory; + } + isNetworked(): this is Networked & this { + return this.networked; + } + constructor(public path: string, private networked: boolean) {} +} + +class FileRep extends FileSystemObject { + constructor(path: string, public content: string) { + super(path, false); + } +} + +class Directory extends FileSystemObject { + children: FileSystemObject[]; +} + +interface Networked { + host: string; +} + +const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo"); + +if (fso.isFile()) { + fso.content; +// ^? +} else if (fso.isDirectory()) { + fso.children; +// ^? +} else if (fso.isNetworked()) { + fso.host; +// ^? +} +``` + +A common use-case for a this-based type guard is to allow for lazy validation of a particular field. For example, this case removes an `undefined` from the value held inside box when `hasValue` has been verified to be true: + +```ts twoslash +class Box { + value?: T; + + hasValue(): this is { value: T } { + return this.value !== undefined; + } +} + +const box = new Box(); +box.value = "Gameboy"; + +box.value; +// ^? + +if (box.hasValue()) { + box.value; + // ^? +} +``` + +## Parameter Properties + +TypeScript offers special syntax for turning a constructor parameter into a class property with the same name and value. +These are called _parameter properties_ and are created by prefixing a constructor argument with one of the visibility modifiers `public`, `private`, `protected`, or `readonly`. +The resulting field gets those modifier(s): + +```ts twoslash +// @errors: 2341 +class Params { + constructor( + public readonly x: number, + protected y: number, + private z: number + ) { + // No body necessary + } +} +const a = new Params(1, 2, 3); +console.log(a.x); +// ^? +console.log(a.z); +``` + +## Class Expressions + +
+

Background Reading:
+ Class expressions (MDN)
+

+
+ +Class expressions are very similar to class declarations. +The only real difference is that class expressions don't need a name, though we can refer to them via whatever identifier they ended up bound to: + +```ts twoslash +const someClass = class { + content: Type; + constructor(value: Type) { + this.content = value; + } +}; + +const m = new someClass("Hello, world"); +// ^? +``` + +## `abstract` Classes and Members + +Classes, methods, and fields in TypeScript may be _abstract_. + +An _abstract method_ or _abstract field_ is one that hasn't had an implementation provided. +These members must exist inside an _abstract class_, which cannot be directly instantiated. + +The role of abstract classes is to serve as a base class for subclasses which do implement all the abstract members. +When a class doesn't have any abstract members, it is said to be _concrete_. + +Let's look at an example + +```ts twoslash +// @errors: 2511 +abstract class Base { + abstract getName(): string; + + printName() { + console.log("Hello, " + this.getName()); + } +} + +const b = new Base(); +``` + +We can't instantiate `Base` with `new` because it's abstract. +Instead, we need to make a derived class and implement the abstract members: + +```ts twoslash +abstract class Base { + abstract getName(): string; + printName() {} +} +// ---cut--- +class Derived extends Base { + getName() { + return "world"; + } +} + +const d = new Derived(); +d.printName(); +``` + +Notice that if we forget to implement the base class's abstract members, we'll get an error: + +```ts twoslash +// @errors: 2515 +abstract class Base { + abstract getName(): string; + printName() {} +} +// ---cut--- +class Derived extends Base { + // forgot to do anything +} +``` + +### Abstract Construct Signatures + +Sometimes you want to accept some class constructor function that produces an instance of a class which derives from some abstract class. + +For example, you might want to write this code: + +```ts twoslash +// @errors: 2511 +abstract class Base { + abstract getName(): string; + printName() {} +} +class Derived extends Base { + getName() { + return ""; + } +} +// ---cut--- +function greet(ctor: typeof Base) { + const instance = new ctor(); + instance.printName(); +} +``` + +TypeScript is correctly telling you that you're trying to instantiate an abstract class. +After all, given the definition of `greet`, it's perfectly legal to write this code, which would end up constructing an abstract class: + +```ts twoslash +declare const greet: any, Base: any; +// ---cut--- +// Bad! +greet(Base); +``` + +Instead, you want to write a function that accepts something with a construct signature: + +```ts twoslash +// @errors: 2345 +abstract class Base { + abstract getName(): string; + printName() {} +} +class Derived extends Base { + getName() { + return ""; + } +} +// ---cut--- +function greet(ctor: new () => Base) { + const instance = new ctor(); + instance.printName(); +} +greet(Derived); +greet(Base); +``` + +Now TypeScript correctly tells you about which class constructor functions can be invoked - `Derived` can because it's concrete, but `Base` cannot. + +## Relationships Between Classes + +In most cases, classes in TypeScript are compared structurally, the same as other types. + +For example, these two classes can be used in place of each other because they're identical: + +```ts twoslash +class Point1 { + x = 0; + y = 0; +} + +class Point2 { + x = 0; + y = 0; +} + +// OK +const p: Point1 = new Point2(); +``` + +Similarly, subtype relationships between classes exist even if there's no explicit inheritance: + +```ts twoslash +// @strict: false +class Person { + name: string; + age: number; +} + +class Employee { + name: string; + age: number; + salary: number; +} + +// OK +const p: Person = new Employee(); +``` + +This sounds straightforward, but there are a few cases that seem stranger than others. + +Empty classes have no members. +In a structural type system, a type with no members is generally a supertype of anything else. +So if you write an empty class (don't!), anything can be used in place of it: + +```ts twoslash +class Empty {} + +function fn(x: Empty) { + // can't do anything with 'x', so I won't +} + +// All OK! +fn(window); +fn({}); +fn(fn); +``` diff --git a/docs/documentation/zh/handbook-v2/Everyday Types.md b/docs/documentation/zh/handbook-v2/Everyday Types.md new file mode 100644 index 00000000..29f3201b --- /dev/null +++ b/docs/documentation/zh/handbook-v2/Everyday Types.md @@ -0,0 +1,714 @@ +--- +title: Everyday Types +layout: docs +permalink: /docs/handbook/2/everyday-types.html +oneline: "The language primitives." +--- + +In this chapter, we'll cover some of the most common types of values you'll find in JavaScript code, and explain the corresponding ways to describe those types in TypeScript. +This isn't an exhaustive list, and future chapters will describe more ways to name and use other types. + +Types can also appear in many more _places_ than just type annotations. +As we learn about the types themselves, we'll also learn about the places where we can refer to these types to form new constructs. + +We'll start by reviewing the most basic and common types you might encounter when writing JavaScript or TypeScript code. +These will later form the core building blocks of more complex types. + +## The primitives: `string`, `number`, and `boolean` + +JavaScript has three very commonly used [primitives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive): `string`, `number`, and `boolean`. +Each has a corresponding type in TypeScript. +As you might expect, these are the same names you'd see if you used the JavaScript `typeof` operator on a value of those types: + +- `string` represents string values like `"Hello, world"` +- `number` is for numbers like `42`. JavaScript does not have a special runtime value for integers, so there's no equivalent to `int` or `float` - everything is simply `number` +- `boolean` is for the two values `true` and `false` + +> The type names `String`, `Number`, and `Boolean` (starting with capital letters) are legal, but refer to some special built-in types that will very rarely appear in your code. _Always_ use `string`, `number`, or `boolean` for types. + +## Arrays + +To specify the type of an array like `[1, 2, 3]`, you can use the syntax `number[]`; this syntax works for any type (e.g. `string[]` is an array of strings, and so on). +You may also see this written as `Array`, which means the same thing. +We'll learn more about the syntax `T` when we cover _generics_. + +> Note that `[number]` is a different thing; refer to the section on [Tuples](/docs/handbook/2/objects.html#tuple-types). + + +## `any` + +TypeScript also has a special type, `any`, that you can use whenever you don't want a particular value to cause typechecking errors. + +When a value is of type `any`, you can access any properties of it (which will in turn be of type `any`), call it like a function, assign it to (or from) a value of any type, or pretty much anything else that's syntactically legal: + +```ts twoslash +let obj: any = { x: 0 }; +// None of the following lines of code will throw compiler errors. +// Using `any` disables all further type checking, and it is assumed +// you know the environment better than TypeScript. +obj.foo(); +obj(); +obj.bar = 100; +obj = "hello"; +const n: number = obj; +``` + +The `any` type is useful when you don't want to write out a long type just to convince TypeScript that a particular line of code is okay. + +### `noImplicitAny` + +When you don't specify a type, and TypeScript can't infer it from context, the compiler will typically default to `any`. + +You usually want to avoid this, though, because `any` isn't type-checked. +Use the compiler flag [`noImplicitAny`](/tsconfig#noImplicitAny) to flag any implicit `any` as an error. + +## Type Annotations on Variables + +When you declare a variable using `const`, `var`, or `let`, you can optionally add a type annotation to explicitly specify the type of the variable: + +```ts twoslash +let myName: string = "Alice"; +// ^^^^^^^^ Type annotation +``` + +> TypeScript doesn't use "types on the left"-style declarations like `int x = 0;` +> Type annotations will always go _after_ the thing being typed. + +In most cases, though, this isn't needed. +Wherever possible, TypeScript tries to automatically _infer_ the types in your code. +For example, the type of a variable is inferred based on the type of its initializer: + +```ts twoslash +// No type annotation needed -- 'myName' inferred as type 'string' +let myName = "Alice"; +``` + +For the most part you don't need to explicitly learn the rules of inference. +If you're starting out, try using fewer type annotations than you think - you might be surprised how few you need for TypeScript to fully understand what's going on. + +## Functions + +Functions are the primary means of passing data around in JavaScript. +TypeScript allows you to specify the types of both the input and output values of functions. + +### Parameter Type Annotations + +When you declare a function, you can add type annotations after each parameter to declare what types of parameters the function accepts. +Parameter type annotations go after the parameter name: + +```ts twoslash +// Parameter type annotation +function greet(name: string) { + // ^^^^^^^^ + console.log("Hello, " + name.toUpperCase() + "!!"); +} +``` + +When a parameter has a type annotation, arguments to that function will be checked: + +```ts twoslash +// @errors: 2345 +declare function greet(name: string): void; +// ---cut--- +// Would be a runtime error if executed! +greet(42); +``` + +> Even if you don't have type annotations on your parameters, TypeScript will still check that you passed the right number of arguments. + +### Return Type Annotations + +You can also add return type annotations. +Return type annotations appear after the parameter list: + +```ts twoslash +function getFavoriteNumber(): number { + // ^^^^^^^^ + return 26; +} +``` + +Much like variable type annotations, you usually don't need a return type annotation because TypeScript will infer the function's return type based on its `return` statements. +The type annotation in the above example doesn't change anything. +Some codebases will explicitly specify a return type for documentation purposes, to prevent accidental changes, or just for personal preference. + +### Anonymous Functions + +Anonymous functions are a little bit different from function declarations. +When a function appears in a place where TypeScript can determine how it's going to be called, the parameters of that function are automatically given types. + +Here's an example: + +```ts twoslash +// @errors: 2551 +// No type annotations here, but TypeScript can spot the bug +const names = ["Alice", "Bob", "Eve"]; + +// Contextual typing for function +names.forEach(function (s) { + console.log(s.toUppercase()); +}); + +// Contextual typing also applies to arrow functions +names.forEach((s) => { + console.log(s.toUppercase()); +}); +``` + +Even though the parameter `s` didn't have a type annotation, TypeScript used the types of the `forEach` function, along with the inferred type of the array, to determine the type `s` will have. + +This process is called _contextual typing_ because the _context_ that the function occurred within informs what type it should have. + +Similar to the inference rules, you don't need to explicitly learn how this happens, but understanding that it _does_ happen can help you notice when type annotations aren't needed. +Later, we'll see more examples of how the context that a value occurs in can affect its type. + +## Object Types + +Apart from primitives, the most common sort of type you'll encounter is an _object type_. +This refers to any JavaScript value with properties, which is almost all of them! +To define an object type, we simply list its properties and their types. + +For example, here's a function that takes a point-like object: + +```ts twoslash +// The parameter's type annotation is an object type +function printCoord(pt: { x: number; y: number }) { + // ^^^^^^^^^^^^^^^^^^^^^^^^ + console.log("The coordinate's x value is " + pt.x); + console.log("The coordinate's y value is " + pt.y); +} +printCoord({ x: 3, y: 7 }); +``` + +Here, we annotated the parameter with a type with two properties - `x` and `y` - which are both of type `number`. +You can use `,` or `;` to separate the properties, and the last separator is optional either way. + +The type part of each property is also optional. +If you don't specify a type, it will be assumed to be `any`. + +### Optional Properties + +Object types can also specify that some or all of their properties are _optional_. +To do this, add a `?` after the property name: + +```ts twoslash +function printName(obj: { first: string; last?: string }) { + // ... +} +// Both OK +printName({ first: "Bob" }); +printName({ first: "Alice", last: "Alisson" }); +``` + +In JavaScript, if you access a property that doesn't exist, you'll get the value `undefined` rather than a runtime error. +Because of this, when you _read_ from an optional property, you'll have to check for `undefined` before using it. + +```ts twoslash +// @errors: 2532 +function printName(obj: { first: string; last?: string }) { + // Error - might crash if 'obj.last' wasn't provided! + console.log(obj.last.toUpperCase()); + if (obj.last !== undefined) { + // OK + console.log(obj.last.toUpperCase()); + } + + // A safe alternative using modern JavaScript syntax: + console.log(obj.last?.toUpperCase()); +} +``` + +## Union Types + +TypeScript's type system allows you to build new types out of existing ones using a large variety of operators. +Now that we know how to write a few types, it's time to start _combining_ them in interesting ways. + +### Defining a Union Type + +The first way to combine types you might see is a _union_ type. +A union type is a type formed from two or more other types, representing values that may be _any one_ of those types. +We refer to each of these types as the union's _members_. + +Let's write a function that can operate on strings or numbers: + +```ts twoslash +// @errors: 2345 +function printId(id: number | string) { + console.log("Your ID is: " + id); +} +// OK +printId(101); +// OK +printId("202"); +// Error +printId({ myID: 22342 }); +``` + +### Working with Union Types + +It's easy to _provide_ a value matching a union type - simply provide a type matching any of the union's members. +If you _have_ a value of a union type, how do you work with it? + +TypeScript will only allow you to do things with the union if that thing is valid for _every_ member of the union. +For example, if you have the union `string | number`, you can't use methods that are only available on `string`: + +```ts twoslash +// @errors: 2339 +function printId(id: number | string) { + console.log(id.toUpperCase()); +} +``` + +The solution is to _narrow_ the union with code, the same as you would in JavaScript without type annotations. +_Narrowing_ occurs when TypeScript can deduce a more specific type for a value based on the structure of the code. + +For example, TypeScript knows that only a `string` value will have a `typeof` value `"string"`: + +```ts twoslash +function printId(id: number | string) { + if (typeof id === "string") { + // In this branch, id is of type 'string' + console.log(id.toUpperCase()); + } else { + // Here, id is of type 'number' + console.log(id); + } +} +``` + +Another example is to use a function like `Array.isArray`: + +```ts twoslash +function welcomePeople(x: string[] | string) { + if (Array.isArray(x)) { + // Here: 'x' is 'string[]' + console.log("Hello, " + x.join(" and ")); + } else { + // Here: 'x' is 'string' + console.log("Welcome lone traveler " + x); + } +} +``` + +Notice that in the `else` branch, we don't need to do anything special - if `x` wasn't a `string[]`, then it must have been a `string`. + +Sometimes you'll have a union where all the members have something in common. +For example, both arrays and strings have a `slice` method. +If every member in a union has a property in common, you can use that property without narrowing: + +```ts twoslash +// Return type is inferred as number[] | string +function getFirstThree(x: number[] | string) { + return x.slice(0, 3); +} +``` + +> It might be confusing that a _union_ of types appears to have the _intersection_ of those types' properties. +> This is not an accident - the name _union_ comes from type theory. +> The _union_ `number | string` is composed by taking the union _of the values_ from each type. +> Notice that given two sets with corresponding facts about each set, only the _intersection_ of those facts applies to the _union_ of the sets themselves. +> For example, if we had a room of tall people wearing hats, and another room of Spanish speakers wearing hats, after combining those rooms, the only thing we know about _every_ person is that they must be wearing a hat. + +## Type Aliases + +We've been using object types and union types by writing them directly in type annotations. +This is convenient, but it's common to want to use the same type more than once and refer to it by a single name. + +A _type alias_ is exactly that - a _name_ for any _type_. +The syntax for a type alias is: + +```ts twoslash +type Point = { + x: number; + y: number; +}; + +// Exactly the same as the earlier example +function printCoord(pt: Point) { + console.log("The coordinate's x value is " + pt.x); + console.log("The coordinate's y value is " + pt.y); +} + +printCoord({ x: 100, y: 100 }); +``` + +You can actually use a type alias to give a name to any type at all, not just an object type. +For example, a type alias can name a union type: + +```ts twoslash +type ID = number | string; +``` + +Note that aliases are _only_ aliases - you cannot use type aliases to create different/distinct "versions" of the same type. +When you use the alias, it's exactly as if you had written the aliased type. +In other words, this code might _look_ illegal, but is OK according to TypeScript because both types are aliases for the same type: + +```ts twoslash +declare function getInput(): string; +declare function sanitize(str: string): string; +// ---cut--- +type UserInputSanitizedString = string; + +function sanitizeInput(str: string): UserInputSanitizedString { + return sanitize(str); +} + +// Create a sanitized input +let userInput = sanitizeInput(getInput()); + +// Can still be re-assigned with a string though +userInput = "new input"; +``` + +## Interfaces + +An _interface declaration_ is another way to name an object type: + +```ts twoslash +interface Point { + x: number; + y: number; +} + +function printCoord(pt: Point) { + console.log("The coordinate's x value is " + pt.x); + console.log("The coordinate's y value is " + pt.y); +} + +printCoord({ x: 100, y: 100 }); +``` + +Just like when we used a type alias above, the example works just as if we had used an anonymous object type. +TypeScript is only concerned with the _structure_ of the value we passed to `printCoord` - it only cares that it has the expected properties. +Being concerned only with the structure and capabilities of types is why we call TypeScript a _structurally typed_ type system. + +### Differences Between Type Aliases and Interfaces + +Type aliases and interfaces are very similar, and in many cases you can choose between them freely. +Almost all features of an `interface` are available in `type`, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable. + + + + + + + + + + + + + + + + +
InterfaceType
+

Extending an interface

+
+interface Animal {
+  name: string
+}
+interface Bear extends Animal { + honey: boolean +}
+const bear = getBear() +bear.name +bear.honey +
+
+

Extending a type via intersections

+
+type Animal = {
+  name: string
+}
+type Bear = Animal & { + honey: boolean +}
+const bear = getBear(); +bear.name; +bear.honey; +
+
+

Adding new fields to an existing interface

+
+interface Window {
+  title: string
+}
+interface Window { + ts: TypeScriptAPI +}
+const src = 'const a = "Hello World"'; +window.ts.transpileModule(src, {}); +
+
+

A type cannot be changed after being created

+
+type Window = {
+  title: string
+}
+type Window = { + ts: TypeScriptAPI +}
+ // Error: Duplicate identifier 'Window'.
+
+
+ +You'll learn more about these concepts in later chapters, so don't worry if you don't understand all of these right away. + +- Prior to TypeScript version 4.2, type alias names [_may_ appear in error messages](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWZWhfYAjABMAMwALA+gbsVjoADqgjKESytQPxCHghAByXigYgBfr8LAsYj8aQMUASbDQcRSExCeCwFiIQh+AKfAYyBiQFgOPyIaikSGLQo0Zj-aazaY+dSaXjLDgAGXgAC9CKhDqAALxJaw2Ib2RzOISuDycLw+ImBYKQflCkWRRD2LXCw6JCxS1JCdJZHJ5RAFIbFJU8ADKC3WzEcnVZaGYE1ABpFnFOmsFhsil2uoHuzwArO9SmAAEIsSFrZB-GgAjjA5gtVN8VCEc1o1C4Q4AGlR2AwO1EsBQoAAbvB-gJ4HhPgB5aDwem-Ph1TCV3AEEirTp4ELtRbTPD4vwKjOfAuioSQHuDXBcnmgACC+eCONFEs73YAPGGZVT5cRyyhiHh7AAON7lsG3vBggB8XGV3l8-nVISOgghxoLq9i7io-AHsayRWGaFrlFauq2rg9qaIGQHwCBqChtKdgRo8TxRjeyB3o+7xAA), sometimes in place of the equivalent anonymous type (which may or may not be desirable). Interfaces will always be named in error messages. +- Type aliases may not participate [in declaration merging, but interfaces can](/play?#code/PTAEEEDtQS0gXApgJwGYEMDGjSfdAIx2UQFoB7AB0UkQBMAoEUfO0Wgd1ADd0AbAK6IAzizp16ALgYM4SNFhwBZdAFtV-UAG8GoPaADmNAcMmhh8ZHAMMAvjLkoM2UCvWad+0ARL0A-GYWVpA29gyY5JAWLJAwGnxmbvGgALzauvpGkCZmAEQAjABMAMwALLkANBl6zABi6DB8okR4Jjg+iPSgABboovDk3jjo5pbW1d6+dGb5djLwAJ7UoABKiJTwjThpnpnGpqPBoTLMAJrkArj4kOTwYmycPOhW6AR8IrDQ8N04wmo4HHQCwYi2Waw2W1S6S8HX8gTGITsQA). +- Interfaces may only be used to [declare the shapes of objects, not rename primitives](/play?#code/PTAEAkFMCdIcgM6gC4HcD2pIA8CGBbABwBtIl0AzUAKBFAFcEBLAOwHMUBPQs0XFgCahWyGBVwBjMrTDJMAshOhMARpD4tQ6FQCtIE5DWoixk9QEEWAeV37kARlABvaqDegAbrmL1IALlAEZGV2agBfampkbgtrWwMAJlAAXmdXdy8ff0Dg1jZwyLoAVWZ2Lh5QVHUJflAlSFxROsY5fFAWAmk6CnRoLGwmILzQQmV8JmQmDzI-SOiKgGV+CaYAL0gBBdyy1KCQ-Pn1AFFplgA5enw1PtSWS+vCsAAVAAtB4QQWOEMKBuYVUiVCYvYQsUTQcRSBDGMGmKSgAAa-VEgiQe2GLgKQA). +- Interface names will [_always_ appear in their original form](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWY2Q-YAjABMAMwALA+gbsVjNXW8yxySoAADaAA0CCaZbPh1XYqXgOIY0ZgmcK0AA0nyaLFhhGY8F4AHJmEJILCWsgZId4NNfIgGFdcIcUTVfgBlZTOWC8T7kAJ42G4eT+GS42QyRaYbCgXAEEguTzeXyCjDBSAAQSE8Ai0Xsl0K9kcziExDeiQs1lAqSE6SyOTy0AKQ2KHk4p1V6s1OuuoHuzwArMagA) in error messages, but _only_ when they are used by name. + +For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind of declaration. If you would like a heuristic, use `interface` until you need to use features from `type`. + +## Type Assertions + +Sometimes you will have information about the type of a value that TypeScript can't know about. + +For example, if you're using `document.getElementById`, TypeScript only knows that this will return _some_ kind of `HTMLElement`, but you might know that your page will always have an `HTMLCanvasElement` with a given ID. + +In this situation, you can use a _type assertion_ to specify a more specific type: + +```ts twoslash +const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement; +``` + +Like a type annotation, type assertions are removed by the compiler and won't affect the runtime behavior of your code. + +You can also use the angle-bracket syntax (except if the code is in a `.tsx` file), which is equivalent: + +```ts twoslash +const myCanvas = document.getElementById("main_canvas"); +``` + +> Reminder: Because type assertions are removed at compile-time, there is no runtime checking associated with a type assertion. +> There won't be an exception or `null` generated if the type assertion is wrong. + +TypeScript only allows type assertions which convert to a _more specific_ or _less specific_ version of a type. +This rule prevents "impossible" coercions like: + +```ts twoslash +// @errors: 2352 +const x = "hello" as number; +``` + +Sometimes this rule can be too conservative and will disallow more complex coercions that might be valid. +If this happens, you can use two assertions, first to `any` (or `unknown`, which we'll introduce later), then to the desired type: + +```ts twoslash +declare const expr: any; +type T = { a: 1; b: 2; c: 3 }; +// ---cut--- +const a = (expr as any) as T; +``` + +## Literal Types + +In addition to the general types `string` and `number`, we can refer to _specific_ strings and numbers in type positions. + +One way to think about this is to consider how JavaScript comes with different ways to declare a variable. Both `var` and `let` allow for changing what is held inside the variable, and `const` does not. This is reflected in how TypeScript creates types for literals. + +```ts twoslash +let changingString = "Hello World"; +changingString = "Olá Mundo"; +// Because `changingString` can represent any possible string, that +// is how TypeScript describes it in the type system +changingString; +// ^? + +const constantString = "Hello World"; +// Because `constantString` can only represent 1 possible string, it +// has a literal type representation +constantString; +// ^? +``` + +By themselves, literal types aren't very valuable: + +```ts twoslash +// @errors: 2322 +let x: "hello" = "hello"; +// OK +x = "hello"; +// ... +x = "howdy"; +``` + +It's not much use to have a variable that can only have one value! + +But by _combining_ literals into unions, you can express a much more useful concept - for example, functions that only accept a certain set of known values: + +```ts twoslash +// @errors: 2345 +function printText(s: string, alignment: "left" | "right" | "center") { + // ... +} +printText("Hello, world", "left"); +printText("G'day, mate", "centre"); +``` + +Numeric literal types work the same way: + +```ts twoslash +function compare(a: string, b: string): -1 | 0 | 1 { + return a === b ? 0 : a > b ? 1 : -1; +} +``` + +Of course, you can combine these with non-literal types: + +```ts twoslash +// @errors: 2345 +interface Options { + width: number; +} +function configure(x: Options | "auto") { + // ... +} +configure({ width: 100 }); +configure("auto"); +configure("automatic"); +``` + +There's one more kind of literal type: boolean literals. +There are only two boolean literal types, and as you might guess, they are the types `true` and `false`. +The type `boolean` itself is actually just an alias for the union `true | false`. + +### Literal Inference + +When you initialize a variable with an object, TypeScript assumes that the properties of that object might change values later. +For example, if you wrote code like this: + +```ts twoslash +declare const someCondition: boolean; +// ---cut--- +const obj = { counter: 0 }; +if (someCondition) { + obj.counter = 1; +} +``` + +TypeScript doesn't assume the assignment of `1` to a field which previously had `0` is an error. +Another way of saying this is that `obj.counter` must have the type `number`, not `0`, because types are used to determine both _reading_ and _writing_ behavior. + +The same applies to strings: + +```ts twoslash +// @errors: 2345 +declare function handleRequest(url: string, method: "GET" | "POST"): void; +// ---cut--- +const req = { url: "https://example.com", method: "GET" }; +handleRequest(req.url, req.method); +``` + +In the above example `req.method` is inferred to be `string`, not `"GET"`. Because code can be evaluated between the creation of `req` and the call of `handleRequest` which could assign a new string like `"GUESS"` to `req.method`, TypeScript considers this code to have an error. + +There are two ways to work around this. + +1. You can change the inference by adding a type assertion in either location: + + ```ts twoslash + declare function handleRequest(url: string, method: "GET" | "POST"): void; + // ---cut--- + // Change 1: + const req = { url: "https://example.com", method: "GET" as "GET" }; + // Change 2 + handleRequest(req.url, req.method as "GET"); + ``` + + Change 1 means "I intend for `req.method` to always have the _literal type_ `"GET"`", preventing the possible assignment of `"GUESS"` to that field after. + Change 2 means "I know for other reasons that `req.method` has the value `"GET"`". + +2. You can use `as const` to convert the entire object to be type literals: + + ```ts twoslash + declare function handleRequest(url: string, method: "GET" | "POST"): void; + // ---cut--- + const req = { url: "https://example.com", method: "GET" } as const; + handleRequest(req.url, req.method); + ``` + +The `as const` suffix acts like `const` but for the type system, ensuring that all properties are assigned the literal type instead of a more general version like `string` or `number`. + +## `null` and `undefined` + +JavaScript has two primitive values used to signal absent or uninitialized value: `null` and `undefined`. + +TypeScript has two corresponding _types_ by the same names. How these types behave depends on whether you have the `strictNullChecks` option on. + +### `strictNullChecks` off + +With `strictNullChecks` _off_, values that might be `null` or `undefined` can still be accessed normally, and the values `null` and `undefined` can be assigned to a property of any type. +This is similar to how languages without null checks (e.g. C#, Java) behave. +The lack of checking for these values tends to be a major source of bugs; we always recommend people turn `strictNullChecks` on if it's practical to do so in their codebase. + +### `strictNullChecks` on + +With `strictNullChecks` _on_, when a value is `null` or `undefined`, you will need to test for those values before using methods or properties on that value. +Just like checking for `undefined` before using an optional property, we can use _narrowing_ to check for values that might be `null`: + +```ts twoslash +function doSomething(x: string | null) { + if (x === null) { + // do nothing + } else { + console.log("Hello, " + x.toUpperCase()); + } +} +``` + +### Non-null Assertion Operator (Postfix `!`) + +TypeScript also has a special syntax for removing `null` and `undefined` from a type without doing any explicit checking. +Writing `!` after any expression is effectively a type assertion that the value isn't `null` or `undefined`: + +```ts twoslash +function liveDangerously(x?: number | null) { + // No error + console.log(x!.toFixed()); +} +``` + +Just like other type assertions, this doesn't change the runtime behavior of your code, so it's important to only use `!` when you know that the value _can't_ be `null` or `undefined`. + +## Enums + +Enums are a feature added to JavaScript by TypeScript which allows for describing a value which could be one of a set of possible named constants. Unlike most TypeScript features, this is _not_ a type-level addition to JavaScript but something added to the language and runtime. Because of this, it's a feature which you should know exists, but maybe hold off on using unless you are sure. You can read more about enums in the [Enum reference page](/docs/handbook/enums.html). + +## Less Common Primitives + +It's worth mentioning the rest of the primitives in JavaScript which are represented in the type system. +Though we will not go into depth here. + +##### `bigint` + +From ES2020 onwards, there is a primitive in JavaScript used for very large integers, `BigInt`: + +```ts twoslash +// @target: es2020 + +// Creating a bigint via the BigInt function +const oneHundred: bigint = BigInt(100); + +// Creating a BigInt via the literal syntax +const anotherHundred: bigint = 100n; +``` + +You can learn more about BigInt in [the TypeScript 3.2 release notes](/docs/handbook/release-notes/typescript-3-2.html#bigint). + +##### `symbol` + +There is a primitive in JavaScript used to create a globally unique reference via the function `Symbol()`: + +```ts twoslash +// @errors: 2367 +const firstName = Symbol("name"); +const secondName = Symbol("name"); + +if (firstName === secondName) { + // Can't ever happen +} +``` + +You can learn more about them in [Symbols reference page](/docs/handbook/symbols.html). diff --git a/docs/documentation/zh/handbook-v2/Modules.md b/docs/documentation/zh/handbook-v2/Modules.md new file mode 100644 index 00000000..29fbc09a --- /dev/null +++ b/docs/documentation/zh/handbook-v2/Modules.md @@ -0,0 +1,385 @@ +--- +title: Modules +layout: docs +permalink: /docs/handbook/2/modules.html +oneline: "How JavaScript handles communicating across file boundaries." +--- + +JavaScript has a long history of different ways to handle modularizing code. +TypeScript having been around since 2012, has implemented support for a lot of these formats, but over time the community and the JavaScript specification has converged on a format called ES Modules (or ES6 modules). You might know it as the `import`/`export` syntax. + +ES Modules was added to the JavaScript spec in 2015, and by 2020 had broad support in most web browsers and JavaScript runtimes. + +For focus, the handbook will cover both ES Modules and its popular pre-cursor CommonJS `module.exports =` syntax, and you can find information about the other module patterns in the reference section under [Modules](/docs/handbook/modules.html). + +## How JavaScript Modules are Defined + +In TypeScript, just as in ECMAScript 2015, any file containing a top-level `import` or `export` is considered a module. + +Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well). + +Modules are executed within their own scope, not in the global scope. +This means that variables, functions, classes, etc. declared in a module are not visible outside the module unless they are explicitly exported using one of the export forms. +Conversely, to consume a variable, function, class, interface, etc. exported from a different module, it has to be imported using one of the import forms. + +## Non-modules + +Before we start, it's important to understand what TypeScript considers a module. +The JavaScript specification declares that any JavaScript files without an `export` or top-level `await` should be considered a script and not a module. + +Inside a script file variables and types are declared to be in the shared global scope, and it's assumed that you'll either use the [`--outFile`](/tsconfig#outFile) compiler option to join multiple input files into one output file, or use multiple ` + + + +
+
+ Compiler:
+ Framework: +
+ + +``` + +## Test + +1. Run the project +2. As you type on the boxes you should see the message appear/change! + +![A GIF of Edge showing the code you have just wrote](https://media.giphy.com/media/U3mTibRAx34DG3zhAN/giphy.gif) + +## Debug + +1. In Edge, press F12 and click the Debugger tab. +2. Look in the first localhost folder, then scripts/app.ts +3. Put a breakpoint on the line with return. +4. Type in the boxes and confirm that the breakpoint hits in TypeScript code and that inspection works correctly. + +![An image showing the debugger running the code you have just wrote](/images/tutorials/aspnet/debugger.png) + +Congrats you've built your own .NET Core project with a TypeScript frontend. diff --git a/docs/documentation/zh/tutorials/Angular.md b/docs/documentation/zh/tutorials/Angular.md new file mode 100644 index 00000000..0a70f50d --- /dev/null +++ b/docs/documentation/zh/tutorials/Angular.md @@ -0,0 +1,14 @@ +--- +title: Angular +layout: docs +permalink: /docs/handbook/angular.html +oneline: Using Angular with TypeScript +deprecated: true +--- + +Angular is a modern framework built entirely in TypeScript, and as a result, using TypeScript with Angular provides a seamless experience. + +The Angular documentation not only supports TypeScript as a first-class citizen, but uses it as its primary language. +With this in mind, [Angular's site](https://angular.io) will always be the most up-to-date reference for using Angular with TypeScript. + +Check out the [quick start guide here](https://angular.io/docs/ts/latest/quickstart.html) to start learning Angular now! diff --git a/docs/documentation/zh/tutorials/Babel with TypeScript.md b/docs/documentation/zh/tutorials/Babel with TypeScript.md new file mode 100644 index 00000000..a898289a --- /dev/null +++ b/docs/documentation/zh/tutorials/Babel with TypeScript.md @@ -0,0 +1,49 @@ +--- +title: Using Babel with TypeScript +layout: docs +permalink: /docs/handbook/babel-with-typescript.html +oneline: How to create a hybrid Babel + TypeScript project +translatable: true +--- + +## Babel vs `tsc` for TypeScript + +When making a modern JavaScript project, you might ask yourself what is the right way to convert files from TypeScript to JavaScript? + +A lot of the time the answer is _"it depends"_, or _"someone may have decided for you"_ depending on the project. If you are building your project with an existing framework like [tsdx](https://tsdx.io), [Angular](https://angular.io/), [NestJS](https://nestjs.com/) or any framework mentioned in the [Getting Started](/docs/home) then this decision is handled for you. + +However, a useful heuristic could be: + +- Is your build output mostly the same as your source input files? Use `tsc` +- Do you need a build pipeline with multiple potential outputs? Use `babel` for transpiling and `tsc` for type checking + +## Babel for transpiling, `tsc` for types + +This is a common pattern for projects with existing build infrastructure which may have been ported from a JavaScript codebase to TypeScript. + +This technique is a hybrid approach, using Babel's [preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript) to generate your JS files, and then using TypeScript to do type checking and `.d.ts` file generation. + +By using babel's support for TypeScript, you get the ability to work with existing build pipelines and are more likely to have a faster JS emit time because Babel does not type check your code. + +#### Type Checking and d.ts file generation + +The downside to using babel is that you don't get type checking during the transition from TS to JS. This can mean that type errors which you miss in your editor could sneak through into production code. + +In addition to that, Babel cannot create `.d.ts` files for your TypeScript which can make it harder to work with your project if it is a library. + +To fix these issues, you would probably want to set up a command to type check your project using TSC. This likely means duplicating some of your babel config into a corresponding [`tsconfig.json`](/tsconfig) and ensuring these flags are enabled: + +```json tsconfig +"compilerOptions": { + // Ensure that .d.ts files are created by tsc, but not .js files + "declaration": true, + "emitDeclarationOnly": true, + // Ensure that Babel can safely transpile files in the TypeScript project + "isolatedModules": true +} +``` + +For more information on these flags: + +- [`isolatedModules`](/tsconfig#isolatedModules) +- [`declaration`](/tsconfig#declaration), [`emitDeclarationOnly`](/tsconfig#emitDeclarationOnly) diff --git a/docs/documentation/zh/tutorials/DOM Manipulation.md b/docs/documentation/zh/tutorials/DOM Manipulation.md new file mode 100755 index 00000000..3e887001 --- /dev/null +++ b/docs/documentation/zh/tutorials/DOM Manipulation.md @@ -0,0 +1,201 @@ +--- +title: DOM Manipulation +layout: docs +permalink: /docs/handbook/dom-manipulation.html +oneline: Using the DOM with TypeScript +translatable: true +--- + +## DOM Manipulation + +### _An exploration into the `HTMLElement` type_ + +In the 20+ years since its standardization, JavaScript has come a very long way. While in 2020, JavaScript can be used on servers, in data science, and even on IoT devices, it is important to remember its most popular use case: web browsers. + +Websites are made up of HTML and/or XML documents. These documents are static, they do not change. The *Document Object Model (DOM)* is a programming interface implemented by browsers in order to make static websites functional. The DOM API can be used to change the document structure, style, and content. The API is so powerful that countless frontend frameworks (jQuery, React, Angular, etc.) have been developed around it in order to make dynamic websites even easier to develop. + +TypeScript is a typed superset of JavaScript, and it ships type definitions for the DOM API. These definitions are readily available in any default TypeScript project. Of the 20,000+ lines of definitions in _lib.dom.d.ts_, one stands out among the rest: `HTMLElement` . This type is the backbone for DOM manipulation with TypeScript. + +> You can explore the source code for the [DOM type definitions](https://github.com/microsoft/TypeScript/blob/main/lib/lib.dom.d.ts) + +## Basic Example + +Given a simplified _index.html_ file: + + + + TypeScript Dom Manipulation + +
+ + + + + +Lets explore a TypeScript script that adds a `

Hello, World!

` element to the `#app` element. + +```ts +// 1. Select the div element using the id property +const app = document.getElementById("app"); + +// 2. Create a new

element programmatically +const p = document.createElement("p"); + +// 3. Add the text content +p.textContent = "Hello, World!"; + +// 4. Append the p element to the div element +app?.appendChild(p); +``` + +After compiling and running the _index.html_ page, the resulting HTML will be: + +```html +
+

Hello, World!

+
+``` + +## The `Document` Interface + +The first line of the TypeScript code uses a global variable `document`. Inspecting the variable shows it is defined by the `Document` interface from the _lib.dom.d.ts_ file. The code snippet contains calls to two methods, `getElementById` and `createElement`. + +### `Document.getElementById` + +The definition for this method is as follows: + +```ts +getElementById(elementId: string): HTMLElement | null; +``` + +Pass it an element id string and it will return either `HTMLElement` or `null` . This method introduces one of the most important types, `HTMLElement`. It serves as the base interface for every other element interface. For example, the `p` variable in the code example is of type `HTMLParagraphElement`. Also take note that this method can return `null`. This is because the method can't be certain pre-runtime if it will be able to actually find the specified element or not. In the last line of the code snippet, the new _optional chaining_ operator is used in order to call `appendChild`. + +### `Document.createElement` + +The definition for this method is (I have omitted the _deprecated_ definition): + +```ts +createElement(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; +createElement(tagName: string, options?: ElementCreationOptions): HTMLElement; +``` + +This is an overloaded function definition. The second overload is simplest and works a lot like the `getElementById` method does. Pass it any `string` and it will return a standard HTMLElement. This definition is what enables developers to create unique HTML element tags. + +For example `document.createElement('xyz')` returns a `` element, clearly not an element that is specified by the HTML specification. + +> For those interested, you can interact with custom tag elements using the `document.getElementsByTagName` + +For the first definition of `createElement`, it is using some advanced generic patterns. It is best understood broken down into chunks, starting with the generic expression: ``. This expression defines a generic parameter `K` that is _constrained_ to the keys of the interface `HTMLElementTagNameMap`. The map interface contains every specified HTML tag name and its corresponding type interface. For example here are the first 5 mapped values: + +```ts +interface HTMLElementTagNameMap { + "a": HTMLAnchorElement; + "abbr": HTMLElement; + "address": HTMLElement; + "applet": HTMLAppletElement; + "area": HTMLAreaElement; + ... +} +``` + +Some elements do not exhibit unique properties and so they just return `HTMLElement`, but other types do have unique properties and methods so they return their specific interface (which will extend from or implement `HTMLElement`). + +Now, for the remainder of the `createElement` definition: `(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]`. The first argument `tagName` is defined as the generic parameter `K` . The TypeScript interpreter is smart enough to _infer_ the generic parameter from this argument. This means that the developer does not actually have to specify the generic parameter when using the method; whatever value is passed to the `tagName` argument will be inferred as `K` and thus can be used throughout the remainder of the definition. Which is exactly what happens; the return value `HTMLElementTagNameMap[K]` takes the `tagName` argument and uses it to return the corresponding type. This definition is how the `p` variable from the code snippet gets a type of `HTMLParagraphElement`. And if the code was `document.createElement('a')`, then it would be an element of type `HTMLAnchorElement`. + +## The `Node` interface + +The `document.getElementById` function returns an `HTMLElement`. `HTMLElement` interface extends the `Element` interface which extends the `Node` interface. This prototypal extension allows for all `HTMLElements` to utilize a subset of standard methods. In the code snippet, we use a property defined on the `Node` interface to append the new `p` element to the website. + +### `Node.appendChild` + +The last line of the code snippet is `app?.appendChild(p)`. The previous, `document.getElementById` , section detailed that the _optional chaining_ operator is used here because `app` can potentially be null at runtime. The `appendChild` method is defined by: + +```ts +appendChild(newChild: T): T; +``` + +This method works similarly to the `createElement` method as the generic parameter `T` is inferred from the `newChild` argument. `T` is _constrained_ to another base interface `Node`. + +## Difference between `children` and `childNodes` + +Previously, this document details the `HTMLElement` interface extends from `Element` which extends from `Node`. In the DOM API there is a concept of _children_ elements. For example in the following HTML, the `p` tags are children of the `div` element + +```tsx +
+

Hello, World

+

TypeScript!

+
; + +const div = document.getElementsByTagName("div")[0]; + +div.children; +// HTMLCollection(2) [p, p] + +div.childNodes; +// NodeList(2) [p, p] +``` + +After capturing the `div` element, the `children` prop will return a `HTMLCollection` list containing the `HTMLParagraphElements`. The `childNodes` property will return a similar `NodeList` list of nodes. Each `p` tag will still be of type `HTMLParagraphElements`, but the `NodeList` can contain additional _HTML nodes_ that the `HTMLCollection` list cannot. + +Modify the html by removing one of the `p` tags, but keep the text. + +```tsx +
+

Hello, World

+ TypeScript! +
; + +const div = document.getElementsByTagName("div")[0]; + +div.children; +// HTMLCollection(1) [p] + +div.childNodes; +// NodeList(2) [p, text] +``` + +See how both lists change. `children` now only contains the `

Hello, World

` element, and the `childNodes` contains a `text` node rather than two `p` nodes. The `text` part of the `NodeList` is the literal `Node` containing the text `TypeScript!`. The `children` list does not contain this `Node` because it is not considered an `HTMLElement`. + +## The `querySelector` and `querySelectorAll` methods + +Both of these methods are great tools for getting lists of dom elements that fit a more unique set of constraints. They are defined in _lib.dom.d.ts_ as: + +```ts +/** + * Returns the first element that is a descendant of node that matches selectors. + */ +querySelector(selectors: K): HTMLElementTagNameMap[K] | null; +querySelector(selectors: K): SVGElementTagNameMap[K] | null; +querySelector(selectors: string): E | null; + +/** + * Returns all element descendants of node that match selectors. + */ +querySelectorAll(selectors: K): NodeListOf; +querySelectorAll(selectors: K): NodeListOf; +querySelectorAll(selectors: string): NodeListOf; +``` + +The `querySelectorAll` definition is similar to `getElementsByTagName`, except it returns a new type: `NodeListOf`. This return type is essentially a custom implementation of the standard JavaScript list element. Arguably, replacing `NodeListOf` with `E[]` would result in a very similar user experience. `NodeListOf` only implements the following properties and methods: `length` , `item(index)`, `forEach((value, key, parent) => void)` , and numeric indexing. Additionally, this method returns a list of _elements_, not _nodes_, which is what `NodeList` was returning from the `.childNodes` method. While this may appear as a discrepancy, take note that interface `Element` extends from `Node`. + +To see these methods in action modify the existing code to: + +```tsx +
    +
  • First :)
  • +
  • Second!
  • +
  • Third times a charm.
  • +
; + +const first = document.querySelector("li"); // returns the first li element +const all = document.querySelectorAll("li"); // returns the list of all li elements +``` + +## Interested in learning more? + +The best part about the _lib.dom.d.ts_ type definitions is that they are reflective of the types annotated in the Mozilla Developer Network (MDN) documentation site. For example, the `HTMLElement` interface is documented by this [HTMLElement page](https://developer.mozilla.org/docs/Web/API/HTMLElement) on MDN. These pages list all available properties, methods, and sometimes even examples. Another great aspect of the pages is that they provide links to the corresponding standard documents. Here is the link to the [W3C Recommendation for HTMLElement](https://www.w3.org/TR/html52/dom.html#htmlelement). + +Sources: + +- [ECMA-262 Standard](http://www.ecma-international.org/ecma-262/10.0/index.html) +- [Introduction to the DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) diff --git a/docs/documentation/zh/tutorials/Gulp.md b/docs/documentation/zh/tutorials/Gulp.md new file mode 100644 index 00000000..ae089c0b --- /dev/null +++ b/docs/documentation/zh/tutorials/Gulp.md @@ -0,0 +1,467 @@ +--- +title: Gulp +layout: docs +permalink: /docs/handbook/gulp.html +oneline: Using TypeScript with Gulp +deprecated: true +--- + +This quick start guide will teach you how to build TypeScript with [gulp](http://gulpjs.com) and then add [Browserify](http://browserify.org), [uglify](http://lisperator.net/uglifyjs/), or [Watchify](https://github.com/substack/watchify) to the gulp pipeline. +This guide also shows how to add [Babel](https://babeljs.io/) functionality using [Babelify](https://github.com/babel/babelify). + +We assume that you're already using [Node.js](https://nodejs.org/) with [npm](https://www.npmjs.com/). + +## Minimal project + +Let's start out with a new directory. +We'll name it `proj` for now, but you can change it to whatever you want. + +```shell +mkdir proj +cd proj +``` + +To start, we're going to structure our project in the following way: + +``` +proj/ + ├─ src/ + └─ dist/ +``` + +TypeScript files will start out in your `src` folder, run through the TypeScript compiler and end up in `dist`. + +Let's scaffold this out: + +```shell +mkdir src +mkdir dist +``` + +## Initialize the project + +Now we'll turn this folder into an npm package. + +```shell +npm init +``` + +You'll be given a series of prompts. +You can use the defaults except for your entry point. +For your entry point, use `./dist/main.js`. +You can always go back and change these in the `package.json` file that's been generated for you. + +## Install our dependencies + +Now we can use `npm install` to install packages. +First install `gulp-cli` globally (if you use a Unix system, you may need to prefix the `npm install` commands in this guide with `sudo`). + +```shell +npm install -g gulp-cli +``` + +Then install `typescript`, `gulp` and `gulp-typescript` in your project's dev dependencies. +[Gulp-typescript](https://www.npmjs.com/package/gulp-typescript) is a gulp plugin for TypeScript. + +```shell +npm install --save-dev typescript gulp@4.0.0 gulp-typescript +``` + +## Write a simple example + +Let's write a Hello World program. +In `src`, create the file `main.ts`: + +```ts +function hello(compiler: string) { + console.log(`Hello from ${compiler}`); +} +hello("TypeScript"); +``` + +In the project root, `proj`, create the file `tsconfig.json`: + +```json tsconfig +{ + "files": ["src/main.ts"], + "compilerOptions": { + "noImplicitAny": true, + "target": "es5" + } +} +``` + +## Create a `gulpfile.js` + +In the project root, create the file `gulpfile.js`: + +```js +var gulp = require("gulp"); +var ts = require("gulp-typescript"); +var tsProject = ts.createProject("tsconfig.json"); + +gulp.task("default", function () { + return tsProject.src().pipe(tsProject()).js.pipe(gulp.dest("dist")); +}); +``` + +## Test the resulting app + +```shell +gulp +node dist/main.js +``` + +The program should print "Hello from TypeScript!". + +## Add modules to the code + +Before we get to Browserify, let's build our code out and add modules to the mix. +This is the structure you're more likely to use for a real app. + +Create a file called `src/greet.ts`: + +```ts +export function sayHello(name: string) { + return `Hello from ${name}`; +} +``` + +Now change the code in `src/main.ts` to import `sayHello` from `greet.ts`: + +```ts +import { sayHello } from "./greet"; + +console.log(sayHello("TypeScript")); +``` + +Finally, add `src/greet.ts` to `tsconfig.json`: + +```json tsconfig +{ + "files": ["src/main.ts", "src/greet.ts"], + "compilerOptions": { + "noImplicitAny": true, + "target": "es5" + } +} +``` + +Make sure that the modules work by running `gulp` and then testing in Node: + +```shell +gulp +node dist/main.js +``` + +Notice that even though we used ES2015 module syntax, TypeScript emitted CommonJS modules that Node uses. +We'll stick with CommonJS for this tutorial, but you could set `module` in the options object to change this. + +## Browserify + +Now let's move this project from Node to the browser. +To do this, we'd like to bundle all our modules into one JavaScript file. +Fortunately, that's exactly what Browserify does. +Even better, it lets us use the CommonJS module system used by Node, which is the default TypeScript emit. +That means our TypeScript and Node setup will transfer to the browser basically unchanged. + +First, install browserify, [tsify](https://www.npmjs.com/package/tsify), and vinyl-source-stream. +tsify is a Browserify plugin that, like gulp-typescript, gives access to the TypeScript compiler. +vinyl-source-stream lets us adapt the file output of Browserify back into a format that gulp understands called [vinyl](https://github.com/gulpjs/vinyl). + +```shell +npm install --save-dev browserify tsify vinyl-source-stream +``` + +## Create a page + +Create a file in `src` named `index.html`: + +```html + + + + + Hello World! + + +

Loading ...

+ + + +``` + +Now change `main.ts` to update the page: + +```ts +import { sayHello } from "./greet"; + +function showHello(divName: string, name: string) { + const elt = document.getElementById(divName); + elt.innerText = sayHello(name); +} + +showHello("greeting", "TypeScript"); +``` + +Calling `showHello` calls `sayHello` to change the paragraph's text. +Now change your gulpfile to the following: + +```js +var gulp = require("gulp"); +var browserify = require("browserify"); +var source = require("vinyl-source-stream"); +var tsify = require("tsify"); +var paths = { + pages: ["src/*.html"], +}; + +gulp.task("copy-html", function () { + return gulp.src(paths.pages).pipe(gulp.dest("dist")); +}); + +gulp.task( + "default", + gulp.series(gulp.parallel("copy-html"), function () { + return browserify({ + basedir: ".", + debug: true, + entries: ["src/main.ts"], + cache: {}, + packageCache: {}, + }) + .plugin(tsify) + .bundle() + .pipe(source("bundle.js")) + .pipe(gulp.dest("dist")); + }) +); +``` + +This adds the `copy-html` task and adds it as a dependency of `default`. +That means any time `default` is run, `copy-html` has to run first. +We've also changed `default` to call Browserify with the tsify plugin instead of gulp-typescript. +Conveniently, they both allow us to pass the same options object to the TypeScript compiler. + +After calling `bundle` we use `source` (our alias for vinyl-source-stream) to name our output bundle `bundle.js`. + +Test the page by running gulp and then opening `dist/index.html` in a browser. +You should see "Hello from TypeScript" on the page. + +Notice that we specified `debug: true` to Browserify. +This causes tsify to emit source maps inside the bundled JavaScript file. +Source maps let you debug your original TypeScript code in the browser instead of the bundled JavaScript. +You can test that source maps are working by opening the debugger for your browser and putting a breakpoint inside `main.ts`. +When you refresh the page the breakpoint should pause the page and let you debug `greet.ts`. + +## Watchify, Babel, and Uglify + +Now that we are bundling our code with Browserify and tsify, we can add various features to our build with browserify plugins. + +- Watchify starts gulp and keeps it running, incrementally compiling whenever you save a file. + This lets you keep an edit-save-refresh cycle going in the browser. + +- Babel is a hugely flexible compiler that converts ES2015 and beyond into ES5 and ES3. + This lets you add extensive and customized transformations that TypeScript doesn't support. + +- Uglify compacts your code so that it takes less time to download. + +## Watchify + +We'll start with Watchify to provide background compilation: + +```shell +npm install --save-dev watchify fancy-log +``` + +Now change your gulpfile to the following: + +```js +var gulp = require("gulp"); +var browserify = require("browserify"); +var source = require("vinyl-source-stream"); +var watchify = require("watchify"); +var tsify = require("tsify"); +var fancy_log = require("fancy-log"); +var paths = { + pages: ["src/*.html"], +}; + +var watchedBrowserify = watchify( + browserify({ + basedir: ".", + debug: true, + entries: ["src/main.ts"], + cache: {}, + packageCache: {}, + }).plugin(tsify) +); + +gulp.task("copy-html", function () { + return gulp.src(paths.pages).pipe(gulp.dest("dist")); +}); + +function bundle() { + return watchedBrowserify + .bundle() + .on("error", fancy_log) + .pipe(source("bundle.js")) + .pipe(gulp.dest("dist")); +} + +gulp.task("default", gulp.series(gulp.parallel("copy-html"), bundle)); +watchedBrowserify.on("update", bundle); +watchedBrowserify.on("log", fancy_log); +``` + +There are basically three changes here, but they require you to refactor your code a bit. + +1. We wrapped our `browserify` instance in a call to `watchify`, and then held on to the result. +2. We called `watchedBrowserify.on('update', bundle);` so that Browserify will run the `bundle` function every time one of your TypeScript files changes. +3. We called `watchedBrowserify.on('log', fancy_log);` to log to the console. + +Together (1) and (2) mean that we have to move our call to `browserify` out of the `default` task. +And we have to give the function for `default` a name since both Watchify and Gulp need to call it. +Adding logging with (3) is optional but very useful for debugging your setup. + +Now when you run Gulp, it should start and stay running. +Try changing the code for `showHello` in `main.ts` and saving it. +You should see output that looks like this: + +```shell +proj$ gulp +[10:34:20] Using gulpfile ~/src/proj/gulpfile.js +[10:34:20] Starting 'copy-html'... +[10:34:20] Finished 'copy-html' after 26 ms +[10:34:20] Starting 'default'... +[10:34:21] 2824 bytes written (0.13 seconds) +[10:34:21] Finished 'default' after 1.36 s +[10:35:22] 2261 bytes written (0.02 seconds) +[10:35:24] 2808 bytes written (0.05 seconds) +``` + +## Uglify + +First install Uglify. +Since the point of Uglify is to mangle your code, we also need to install vinyl-buffer and gulp-sourcemaps to keep sourcemaps working. + +```shell +npm install --save-dev gulp-uglify vinyl-buffer gulp-sourcemaps +``` + +Now change your gulpfile to the following: + +```js +var gulp = require("gulp"); +var browserify = require("browserify"); +var source = require("vinyl-source-stream"); +var tsify = require("tsify"); +var uglify = require("gulp-uglify"); +var sourcemaps = require("gulp-sourcemaps"); +var buffer = require("vinyl-buffer"); +var paths = { + pages: ["src/*.html"], +}; + +gulp.task("copy-html", function () { + return gulp.src(paths.pages).pipe(gulp.dest("dist")); +}); + +gulp.task( + "default", + gulp.series(gulp.parallel("copy-html"), function () { + return browserify({ + basedir: ".", + debug: true, + entries: ["src/main.ts"], + cache: {}, + packageCache: {}, + }) + .plugin(tsify) + .bundle() + .pipe(source("bundle.js")) + .pipe(buffer()) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(uglify()) + .pipe(sourcemaps.write("./")) + .pipe(gulp.dest("dist")); + }) +); +``` + +Notice that `uglify` itself has just one call — the calls to `buffer` and `sourcemaps` exist to make sure sourcemaps keep working. +These calls give us a separate sourcemap file instead of using inline sourcemaps like before. +Now you can run Gulp and check that `bundle.js` does get minified into an unreadable mess: + +```shell +gulp +cat dist/bundle.js +``` + +## Babel + +First install Babelify and the Babel preset for ES2015. +Like Uglify, Babelify mangles code, so we'll need vinyl-buffer and gulp-sourcemaps. +By default Babelify will only process files with extensions of `.js`, `.es`, `.es6` and `.jsx` so we need to add the `.ts` extension as an option to Babelify. + +```shell +npm install --save-dev babelify@8 babel-core babel-preset-es2015 vinyl-buffer gulp-sourcemaps +``` + +Now change your gulpfile to the following: + +```js +var gulp = require("gulp"); +var browserify = require("browserify"); +var source = require("vinyl-source-stream"); +var tsify = require("tsify"); +var sourcemaps = require("gulp-sourcemaps"); +var buffer = require("vinyl-buffer"); +var paths = { + pages: ["src/*.html"], +}; + +gulp.task("copy-html", function () { + return gulp.src(paths.pages).pipe(gulp.dest("dist")); +}); + +gulp.task( + "default", + gulp.series(gulp.parallel("copy-html"), function () { + return browserify({ + basedir: ".", + debug: true, + entries: ["src/main.ts"], + cache: {}, + packageCache: {}, + }) + .plugin(tsify) + .transform("babelify", { + presets: ["es2015"], + extensions: [".ts"], + }) + .bundle() + .pipe(source("bundle.js")) + .pipe(buffer()) + .pipe(sourcemaps.init({ loadMaps: true })) + .pipe(sourcemaps.write("./")) + .pipe(gulp.dest("dist")); + }) +); +``` + +We also need to have TypeScript target ES2015. +Babel will then produce ES5 from the ES2015 code that TypeScript emits. +Let's modify `tsconfig.json`: + +```json tsconfig +{ + "files": ["src/main.ts"], + "compilerOptions": { + "noImplicitAny": true, + "target": "es2015" + } +} +``` + +Babel's ES5 output should be very similar to TypeScript's output for such a simple script. diff --git a/docs/documentation/zh/tutorials/Migrating from JavaScript.md b/docs/documentation/zh/tutorials/Migrating from JavaScript.md new file mode 100644 index 00000000..be31153a --- /dev/null +++ b/docs/documentation/zh/tutorials/Migrating from JavaScript.md @@ -0,0 +1,442 @@ +--- +title: Migrating from JavaScript +layout: docs +permalink: /docs/handbook/migrating-from-javascript.html +oneline: How to migrate from JavaScript to TypeScript +--- + +TypeScript doesn't exist in a vacuum. +It was built with the JavaScript ecosystem in mind, and a lot of JavaScript exists today. +Converting a JavaScript codebase over to TypeScript is, while somewhat tedious, usually not challenging. +In this tutorial, we're going to look at how you might start out. +We assume you've read enough of the handbook to write new TypeScript code. + +If you're looking to convert a React project, we recommend looking at the [React Conversion Guide](https://github.com/Microsoft/TypeScript-React-Conversion-Guide#typescript-react-conversion-guide) first. + +## Setting up your Directories + +If you're writing in plain JavaScript, it's likely that you're running your JavaScript directly, +where your `.js` files are in a `src`, `lib`, or `dist` directory, and then ran as desired. + +If that's the case, the files that you've written are going to be used as inputs to TypeScript, and you'll run the outputs it produces. +During our JS to TS migration, we'll need to separate our input files to prevent TypeScript from overwriting them. +If your output files need to reside in a specific directory, then that will be your output directory. + +You might also be running some intermediate steps on your JavaScript, such as bundling or using another transpiler like Babel. +In this case, you might already have a folder structure like this set up. + +From this point on, we're going to assume that your directory is set up something like this: + +``` +projectRoot +├── src +│ ├── file1.js +│ └── file2.js +├── built +└── tsconfig.json +``` + +If you have a `tests` folder outside of your `src` directory, you might have one `tsconfig.json` in `src`, and one in `tests` as well. + +## Writing a Configuration File + +TypeScript uses a file called `tsconfig.json` for managing your project's options, such as which files you want to include, and what sorts of checking you want to perform. +Let's create a bare-bones one for our project: + +```json +{ + "compilerOptions": { + "outDir": "./built", + "allowJs": true, + "target": "es5" + }, + "include": ["./src/**/*"] +} +``` + +Here we're specifying a few things to TypeScript: + +1. Read in any files it understands in the `src` directory (with `include`). +2. Accept JavaScript files as inputs (with `allowJs`). +3. Emit all of the output files in `built` (with `outDir`). +4. Translate newer JavaScript constructs down to an older version like ECMAScript 5 (using `target`). + +At this point, if you try running `tsc` at the root of your project, you should see output files in the `built` directory. +The layout of files in `built` should look identical to the layout of `src`. +You should now have TypeScript working with your project. + +## Early Benefits + +Even at this point you can get some great benefits from TypeScript understanding your project. +If you open up an editor like [VS Code](https://code.visualstudio.com) or [Visual Studio](https://visualstudio.com), you'll see that you can often get some tooling support like completion. +You can also catch certain bugs with options like: + +- `noImplicitReturns` which prevents you from forgetting to return at the end of a function. +- `noFallthroughCasesInSwitch` which is helpful if you never want to forget a `break` statement between `case`s in a `switch` block. + +TypeScript will also warn about unreachable code and labels, which you can disable with `allowUnreachableCode` and `allowUnusedLabels` respectively. + +## Integrating with Build Tools + +You might have some more build steps in your pipeline. +Perhaps you concatenate something to each of your files. +Each build tool is different, but we'll do our best to cover the gist of things. + +## Gulp + +If you're using Gulp in some fashion, we have a tutorial on [using Gulp](/docs/handbook/gulp.html) with TypeScript, and integrating with common build tools like Browserify, Babelify, and Uglify. +You can read more there. + +## Webpack + +Webpack integration is pretty simple. +You can use `ts-loader`, a TypeScript loader, combined with `source-map-loader` for easier debugging. +Simply run + +```shell +npm install ts-loader source-map-loader +``` + +and merge in options from the following into your `webpack.config.js` file: + +```js +module.exports = { + entry: "./src/index.ts", + output: { + filename: "./dist/bundle.js", + }, + + // Enable sourcemaps for debugging webpack's output. + devtool: "source-map", + + resolve: { + // Add '.ts' and '.tsx' as resolvable extensions. + extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"], + }, + + module: { + rules: [ + // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'. + { test: /\.tsx?$/, loader: "ts-loader" }, + + // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. + { test: /\.js$/, loader: "source-map-loader" }, + ], + }, + + // Other options... +}; +``` + +It's important to note that ts-loader will need to run before any other loader that deals with `.js` files. + +The same goes for [awesome-typescript-loader](https://github.com/TypeStrong/ts-loader), another TypeScript loader for Webpack. +You can read more about the differences between the two [here](https://github.com/s-panferov/awesome-typescript-loader#differences-between-ts-loader). + +You can see an example of using Webpack in our [tutorial on React and Webpack](/docs/handbook/react-&-webpack.html). + +## Moving to TypeScript Files + +At this point, you're probably ready to start using TypeScript files. +The first step is to rename one of your `.js` files to `.ts`. +If your file uses JSX, you'll need to rename it to `.tsx`. + +Finished with that step? +Great! +You've successfully migrated a file from JavaScript to TypeScript! + +Of course, that might not feel right. +If you open that file in an editor with TypeScript support (or if you run `tsc --pretty`), you might see red squiggles on certain lines. +You should think of these the same way you'd think of red squiggles in an editor like Microsoft Word. +TypeScript will still translate your code, just like Word will still let you print your documents. + +If that sounds too lax for you, you can tighten that behavior up. +If, for instance, you _don't_ want TypeScript to compile to JavaScript in the face of errors, you can use the `noEmitOnError` option. +In that sense, TypeScript has a dial on its strictness, and you can turn that knob up as high as you want. + +If you plan on using the stricter settings that are available, it's best to turn them on now (see [Getting Stricter Checks](#getting-stricter-checks) below). +For instance, if you never want TypeScript to silently infer `any` for a type without you explicitly saying so, you can use `noImplicitAny` before you start modifying your files. +While it might feel somewhat overwhelming, the long-term gains become apparent much more quickly. + +## Weeding out Errors + +Like we mentioned, it's not unexpected to get error messages after conversion. +The important thing is to actually go one by one through these and decide how to deal with the errors. +Often these will be legitimate bugs, but sometimes you'll have to explain what you're trying to do a little better to TypeScript. + +### Importing from Modules + +You might start out getting a bunch of errors like `Cannot find name 'require'.`, and `Cannot find name 'define'.`. +In these cases, it's likely that you're using modules. +While you can just convince TypeScript that these exist by writing out + +```ts +// For Node/CommonJS +declare function require(path: string): any; +``` + +or + +```ts +// For RequireJS/AMD +declare function define(...args: any[]): any; +``` + +it's better to get rid of those calls and use TypeScript syntax for imports. + +First, you'll need to enable some module system by setting TypeScript's `module` flag. +Valid options are `commonjs`, `amd`, `system`, and `umd`. + +If you had the following Node/CommonJS code: + +```js +var foo = require("foo"); + +foo.doStuff(); +``` + +or the following RequireJS/AMD code: + +```js +define(["foo"], function (foo) { + foo.doStuff(); +}); +``` + +then you would write the following TypeScript code: + +```ts +import foo = require("foo"); + +foo.doStuff(); +``` + +### Getting Declaration Files + +If you started converting over to TypeScript imports, you'll probably run into errors like `Cannot find module 'foo'.`. +The issue here is that you likely don't have _declaration files_ to describe your library. +Luckily this is pretty easy. +If TypeScript complains about a package like `lodash`, you can just write + +```shell +npm install -S @types/lodash +``` + +If you're using a module option other than `commonjs`, you'll need to set your `moduleResolution` option to `node`. + +After that, you'll be able to import lodash with no issues, and get accurate completions. + +### Exporting from Modules + +Typically, exporting from a module involves adding properties to a value like `exports` or `module.exports`. +TypeScript allows you to use top-level export statements. +For instance, if you exported a function like so: + +```js +module.exports.feedPets = function (pets) { + // ... +}; +``` + +you could write that out as the following: + +```ts +export function feedPets(pets) { + // ... +} +``` + +Sometimes you'll entirely overwrite the exports object. +This is a common pattern people use to make their modules immediately callable like in this snippet: + +```js +var express = require("express"); +var app = express(); +``` + +You might have previously written that like so: + +```js +function foo() { + // ... +} +module.exports = foo; +``` + +In TypeScript, you can model this with the `export =` construct. + +```ts +function foo() { + // ... +} +export = foo; +``` + +### Too many/too few arguments + +You'll sometimes find yourself calling a function with too many/few arguments. +Typically, this is a bug, but in some cases, you might have declared a function that uses the `arguments` object instead of writing out any parameters: + +```js +function myCoolFunction() { + if (arguments.length == 2 && !Array.isArray(arguments[1])) { + var f = arguments[0]; + var arr = arguments[1]; + // ... + } + // ... +} + +myCoolFunction( + function (x) { + console.log(x); + }, + [1, 2, 3, 4] +); +myCoolFunction( + function (x) { + console.log(x); + }, + 1, + 2, + 3, + 4 +); +``` + +In this case, we need to use TypeScript to tell any of our callers about the ways `myCoolFunction` can be called using function overloads. + +```ts +function myCoolFunction(f: (x: number) => void, nums: number[]): void; +function myCoolFunction(f: (x: number) => void, ...nums: number[]): void; +function myCoolFunction() { + if (arguments.length == 2 && !Array.isArray(arguments[1])) { + var f = arguments[0]; + var arr = arguments[1]; + // ... + } + // ... +} +``` + +We added two overload signatures to `myCoolFunction`. +The first checks states that `myCoolFunction` takes a function (which takes a `number`), and then a list of `number`s. +The second one says that it will take a function as well, and then uses a rest parameter (`...nums`) to state that any number of arguments after that need to be `number`s. + +### Sequentially Added Properties + +Some people find it more aesthetically pleasing to create an object and add properties immediately after like so: + +```js +var options = {}; +options.color = "red"; +options.volume = 11; +``` + +TypeScript will say that you can't assign to `color` and `volume` because it first figured out the type of `options` as `{}` which doesn't have any properties. +If you instead moved the declarations into the object literal themselves, you'd get no errors: + +```ts +let options = { + color: "red", + volume: 11, +}; +``` + +You could also define the type of `options` and add a type assertion on the object literal. + +```ts +interface Options { + color: string; + volume: number; +} + +let options = {} as Options; +options.color = "red"; +options.volume = 11; +``` + +Alternatively, you can just say `options` has the type `any` which is the easiest thing to do, but which will benefit you the least. + +### `any`, `Object`, and `{}` + +You might be tempted to use `Object` or `{}` to say that a value can have any property on it because `Object` is, for most purposes, the most general type. +However **`any` is actually the type you want to use** in those situations, since it's the most _flexible_ type. + +For instance, if you have something that's typed as `Object` you won't be able to call methods like `toLowerCase()` on it. +Being more general usually means you can do less with a type, but `any` is special in that it is the most general type while still allowing you to do anything with it. +That means you can call it, construct it, access properties on it, etc. +Keep in mind though, whenever you use `any`, you lose out on most of the error checking and editor support that TypeScript gives you. + +If a decision ever comes down to `Object` and `{}`, you should prefer `{}`. +While they are mostly the same, technically `{}` is a more general type than `Object` in certain esoteric cases. + +## Getting Stricter Checks + +TypeScript comes with certain checks to give you more safety and analysis of your program. +Once you've converted your codebase to TypeScript, you can start enabling these checks for greater safety. + +### No Implicit `any` + +There are certain cases where TypeScript can't figure out what certain types should be. +To be as lenient as possible, it will decide to use the type `any` in its place. +While this is great for migration, using `any` means that you're not getting any type safety, and you won't get the same tooling support you'd get elsewhere. +You can tell TypeScript to flag these locations down and give an error with the `noImplicitAny` option. + +### Strict `null` & `undefined` Checks + +By default, TypeScript assumes that `null` and `undefined` are in the domain of every type. +That means anything declared with the type `number` could be `null` or `undefined`. +Since `null` and `undefined` are such a frequent source of bugs in JavaScript and TypeScript, TypeScript has the `strictNullChecks` option to spare you the stress of worrying about these issues. + +When `strictNullChecks` is enabled, `null` and `undefined` get their own types called `null` and `undefined` respectively. +Whenever anything is _possibly_ `null`, you can use a union type with the original type. +So for instance, if something could be a `number` or `null`, you'd write the type out as `number | null`. + +If you ever have a value that TypeScript thinks is possibly `null`/`undefined`, but you know better, you can use the postfix `!` operator to tell it otherwise. + +```ts +declare var foo: string[] | null; + +foo.length; // error - 'foo' is possibly 'null' + +foo!.length; // okay - 'foo!' just has type 'string[]' +``` + +As a heads up, when using `strictNullChecks`, your dependencies may need to be updated to use `strictNullChecks` as well. + +### No Implicit `any` for `this` + +When you use the `this` keyword outside of classes, it has the type `any` by default. +For instance, imagine a `Point` class, and imagine a function that we wish to add as a method: + +```ts +class Point { + constructor(public x, public y) {} + getDistance(p: Point) { + let dx = p.x - this.x; + let dy = p.y - this.y; + return Math.sqrt(dx ** 2 + dy ** 2); + } +} +// ... + +// Reopen the interface. +interface Point { + distanceFromOrigin(): number; +} +Point.prototype.distanceFromOrigin = function () { + return this.getDistance({ x: 0, y: 0 }); +}; +``` + +This has the same problems we mentioned above - we could easily have misspelled `getDistance` and not gotten an error. +For this reason, TypeScript has the `noImplicitThis` option. +When that option is set, TypeScript will issue an error when `this` is used without an explicit (or inferred) type. +The fix is to use a `this`-parameter to give an explicit type in the interface or in the function itself: + +```ts +Point.prototype.distanceFromOrigin = function (this: Point) { + return this.getDistance({ x: 0, y: 0 }); +}; +``` diff --git a/docs/documentation/zh/tutorials/React.md b/docs/documentation/zh/tutorials/React.md new file mode 100644 index 00000000..773ea021 --- /dev/null +++ b/docs/documentation/zh/tutorials/React.md @@ -0,0 +1,26 @@ +--- +title: React +layout: docs +permalink: /docs/handbook/react.html +oneline: Links to learn about TypeScript and React +translatable: true +--- + +TypeScript supports [JSX](/docs/handbook/jsx.html) and can correctly model the patterns used in React codebases like `useState`. + +### Getting Set Up With a React Project + +Today there are many frameworks which support TypeScript out of the box: + +- [Create React App](https://create-react-app.dev) - [TS docs](https://create-react-app.dev/docs/adding-typescript/) +- [Next.js](https://nextjs.org) - [TS docs](https://nextjs.org/learn/excel/typescript) +- [Gatsby](https://www.gatsbyjs.org) - [TS Docs](https://www.gatsbyjs.org/docs/typescript/) + +All of these are great starting points. We [use Gatsby](https://www.gatsbyjs.org/blog/2020-01-23-why-typescript-chose-gatsby/#reach-skip-nav) with TypeScript for [this website](https://github.com/microsoft/TypeScript-Website/), so that can also be a useful reference implementation. + +### Documentation + +Here are some of the best places to find up-to-date information on React and TypeScript: + +- [React TypeScript Cheatsheets](https://react-typescript-cheatsheet.netlify.app) +- [React & Redux in TypeScript](https://github.com/piotrwitek/react-redux-typescript-guide#react--redux-in-typescript---complete-guide) diff --git a/docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md b/docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md new file mode 100644 index 00000000..b056c7f3 --- /dev/null +++ b/docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md @@ -0,0 +1,187 @@ +--- +title: TypeScript Tooling in 5 minutes +layout: docs +permalink: /docs/handbook/typescript-tooling-in-5-minutes.html +oneline: A tutorial to understand how to create a small website with TypeScript +translatable: true +--- + +Let's get started by building a simple web application with TypeScript. + +## Installing TypeScript + +There are two main ways to get the TypeScript available for your project: + +- Via npm (the Node.js package manager) +- By installing TypeScript's Visual Studio plugins + +Visual Studio 2017 and Visual Studio 2015 Update 3 include TypeScript by default. +If you didn't install TypeScript with Visual Studio, you can still [download it](/download). + +For npm users: + +```shell +> npm install -g typescript +``` + +## Building your first TypeScript file + +In your editor, type the following JavaScript code in `greeter.ts`: + +```ts twoslash +// @noImplicitAny: false +function greeter(person) { + return "Hello, " + person; +} + +let user = "Jane User"; + +document.body.textContent = greeter(user); +``` + +## Compiling your code + +We used a `.ts` extension, but this code is just JavaScript. +You could have copy/pasted this straight out of an existing JavaScript app. + +At the command line, run the TypeScript compiler: + +```shell +tsc greeter.ts +``` + +The result will be a file `greeter.js` which contains the same JavaScript that you fed in. +We're up and running using TypeScript in our JavaScript app! + +Now we can start taking advantage of some of the new tools TypeScript offers. +Add a `: string` type annotation to the 'person' function argument as shown here: + +```ts twoslash +function greeter(person: string) { + return "Hello, " + person; +} + +let user = "Jane User"; + +document.body.textContent = greeter(user); +``` + +## Type annotations + +Type annotations in TypeScript are lightweight ways to record the intended contract of the function or variable. +In this case, we intend the greeter function to be called with a single string parameter. +We can try changing the call greeter to pass an array instead: + +```ts twoslash +// @errors: 2345 +function greeter(person: string) { + return "Hello, " + person; +} + +let user = [0, 1, 2]; + +document.body.textContent = greeter(user); +``` + +Re-compiling, you'll now see an error: + +```shell +error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'. +``` + +Similarly, try removing all the arguments to the greeter call. +TypeScript will let you know that you have called this function with an unexpected number of parameters. +In both cases, TypeScript can offer static analysis based on both the structure of your code, and the type annotations you provide. + +Notice that although there were errors, the `greeter.js` file is still created. +You can use TypeScript even if there are errors in your code. But in this case, TypeScript is warning that your code will likely not run as expected. + +## Interfaces + +Let's develop our sample further. Here we use an interface that describes objects that have a firstName and lastName field. +In TypeScript, two types are compatible if their internal structure is compatible. +This allows us to implement an interface just by having the shape the interface requires, without an explicit `implements` clause. + +```ts twoslash +interface Person { + firstName: string; + lastName: string; +} + +function greeter(person: Person) { + return "Hello, " + person.firstName + " " + person.lastName; +} + +let user = { firstName: "Jane", lastName: "User" }; + +document.body.textContent = greeter(user); +``` + +## Classes + +Finally, let's extend the example one last time with classes. +TypeScript supports new features in JavaScript, like support for class-based object-oriented programming. + +Here we're going to create a `Student` class with a constructor and a few public fields. +Notice that classes and interfaces play well together, letting the programmer decide on the right level of abstraction. + +Also of note, the use of `public` on arguments to the constructor is a shorthand that allows us to automatically create properties with that name. + +```ts twoslash +class Student { + fullName: string; + constructor( + public firstName: string, + public middleInitial: string, + public lastName: string + ) { + this.fullName = firstName + " " + middleInitial + " " + lastName; + } +} + +interface Person { + firstName: string; + lastName: string; +} + +function greeter(person: Person) { + return "Hello, " + person.firstName + " " + person.lastName; +} + +let user = new Student("Jane", "M.", "User"); + +document.body.textContent = greeter(user); +``` + +Re-run `tsc greeter.ts` and you'll see the generated JavaScript is the same as the earlier code. +Classes in TypeScript are just a shorthand for the same prototype-based OO that is frequently used in JavaScript. + +## Running your TypeScript web app + +Now type the following in `greeter.html`: + +```html + + + + TypeScript Greeter + + + + + +``` + +Open `greeter.html` in the browser to run your first simple TypeScript web application! + +Optional: Open `greeter.ts` in Visual Studio, or copy the code into the TypeScript playground. +You can hover over identifiers to see their types. +Notice that in some cases these types are inferred automatically for you. +Re-type the last line, and see completion lists and parameter help based on the types of the DOM elements. +Put your cursor on the reference to the greeter function, and hit F12 to go to its definition. +Notice, too, that you can right-click on a symbol and use refactoring to rename it. + +The type information provided works together with the tools to work with JavaScript at application scale. +For more examples of what's possible in TypeScript, see the Samples section of the website. + +![Visual Studio picture](/images/docs/greet_person.png) From 10af170b9811e218727e234cee4c506e3ebfff37 Mon Sep 17 00:00:00 2001 From: zhouLion Date: Wed, 8 Sep 2021 09:51:21 +0800 Subject: [PATCH 02/15] ZH translation: translate some short files --- .../_Creating Types from Types.md | 26 +++++++++---------- docs/documentation/zh/tutorials/Angular.md | 11 ++++---- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md index 349608c5..3c4e697a 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md @@ -2,21 +2,21 @@ title: Creating Types from Types layout: docs permalink: /docs/handbook/2/types-from-types.html -oneline: "An overview of the ways in which you can create more types from existing types." +oneline: "您可通过现有类型创建更多类型的几种方式概览。" --- -TypeScript's type system is very powerful because it allows expressing types _in terms of other types_. +TypeScript 的类型系统非常强大,因为它允许用其他类型表示类型。 -The simplest form of this idea is generics, we actually have a wide variety of _type operators_ available to us. -It's also possible to express types in terms of _values_ that we already have. +这个说法的最简单的形式就是泛型,实际上我们有各种各样的类型运算符。 +也可以用我们已有的 _值_ 来表示类型。 -By combining various type operators, we can express complex operations and values in a succinct, maintainable way. -In this section we'll cover ways to express a new type in terms of an existing type or value. +通过组合各种类型的运算符,我们可以以简洁、可维护的方式表达复杂的操作和值。 +在本节中,我们将介绍用现有类型或值表示新类型的方法。 -- [Generics](/docs/handbook/2/generics.html) - Types which take parameters -- [Keyof Type Operator](/docs/handbook/2/keyof-types.html) - Using the `keyof` operator to create new types -- [Typeof Type Operator](/docs/handbook/2/typeof-types.html) - Using the `typeof` operator to create new types -- [Indexed Access Types](/docs/handbook/2/indexed-access-types.html) - Using `Type['a']` syntax to access a subset of a type -- [Conditional Types](/docs/handbook/2/conditional-types.html) - Types which act like if statements in the type system -- [Mapped Types](/docs/handbook/2/mapped-types.html) - Creating types by mapping each property in an existing type -- [Template Literal Types](/docs/handbook/2/template-literal-types.html) - Mapped types which change properties via template literal strings +- [泛型](/docs/handbook/2/generics.html) - 接收参数的类型 +- [Keyof 类型运算符](/docs/handbook/2/keyof-types.html) - 通过 `keyof` 运算符创建新类型 +- [Typeof 类型运算符](/docs/handbook/2/typeof-types.html) - 通过 `typeof` 运算符创建新类型 +- [按索引访问类型](/docs/handbook/2/indexed-access-types.html) - 通过 `Type['a']` 语法访问一个类型的子集 +- [条件类型](/docs/handbook/2/conditional-types.html) - 在类型系统中像 if 语句那样的类型 +- [映射类型](/docs/handbook/2/mapped-types.html) - 通过已有类型的属性映射创建类型 +- [模版字面量类型](/docs/handbook/2/template-literal-types.html) - 已映射类型,其通过模版字面量字符串,改变其属性 diff --git a/docs/documentation/zh/tutorials/Angular.md b/docs/documentation/zh/tutorials/Angular.md index 0a70f50d..c45fff80 100644 --- a/docs/documentation/zh/tutorials/Angular.md +++ b/docs/documentation/zh/tutorials/Angular.md @@ -1,14 +1,13 @@ --- title: Angular layout: docs -permalink: /docs/handbook/angular.html -oneline: Using Angular with TypeScript +permalink: /zh/docs/handbook/angular.html +oneline: 在 Angular 中使用 TypeScript deprecated: true --- -Angular is a modern framework built entirely in TypeScript, and as a result, using TypeScript with Angular provides a seamless experience. +Angular 是一个完全用 TypeScript 构建的现代框架,因此,将 TypeScript 与 Angular 结合使用可以提供无缝体验。 -The Angular documentation not only supports TypeScript as a first-class citizen, but uses it as its primary language. -With this in mind, [Angular's site](https://angular.io) will always be the most up-to-date reference for using Angular with TypeScript. +Angular 文档支持将 TypeScript 作为一级公民,而且将其作为主要语言。考虑到这一点,[Angular的网站](https://angular.io) 将始终是使用 Angular 和 TypeScript 的最新参考。 -Check out the [quick start guide here](https://angular.io/docs/ts/latest/quickstart.html) to start learning Angular now! +查看 [快速入门指引]](https://angular.io/docs/ts/latest/quickstart.html) 开始学习 Angular 吧! From 5b2a4f4b296bafbd33994474f688b852dfeb0261 Mon Sep 17 00:00:00 2001 From: zhouLion Date: Wed, 8 Sep 2021 11:30:19 +0800 Subject: [PATCH 03/15] ZH translation: translate Creating DTS files From JS --- .../javascript/Creating DTS files From JS.md | 62 ++++++++++--------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/docs/documentation/zh/javascript/Creating DTS files From JS.md b/docs/documentation/zh/javascript/Creating DTS files From JS.md index 4ef02392..b0509a7e 100644 --- a/docs/documentation/zh/javascript/Creating DTS files From JS.md +++ b/docs/documentation/zh/javascript/Creating DTS files From JS.md @@ -1,34 +1,34 @@ --- title: Creating .d.ts Files from .js files layout: docs -permalink: /docs/handbook/declaration-files/dts-from-js.html -oneline: "How to add d.ts generation to JavaScript projects" +permalink: /zh/docs/handbook/declaration-files/dts-from-js.html +oneline: "如何生成并添加 .d.ts 到 JavaScript 项目" translatable: true --- -[With TypeScript 3.7](/docs/handbook/release-notes/typescript-3-7.html#--declaration-and---allowjs), -TypeScript added support for generating .d.ts files from JavaScript using JSDoc syntax. +[使用 TypeScript 3.7](/docs/handbook/release-notes/typescript-3-7.html#--declaration-and---allowjs), +TypeScript 新增了对使用 JSDoc 语法的 JavaScript,生成 .d.ts 文件的支持。 -This set up means you can own the editor experience of TypeScript-powered editors without porting your project to TypeScript, or having to maintain .d.ts files in your codebase. -TypeScript supports most JSDoc tags, you can find [the reference here](/docs/handbook/type-checking-javascript-files.html#supported-jsdoc). +这种设置意味着,您可以拥有 TypeScript 支持的编辑器的编辑器体验,而无需将项目移植到TypeScript,也无需在代码库中维护.d.ts文件。 -## Setting up your Project to emit .d.ts files +TypeScript 支持绝大多数的 JSDoc 标签,您可以参考 [这里的手册](/docs/handbook/type-checking-javascript-files.html#supported-jsdoc)。 -To add creation of .d.ts files in your project, you will need to do up-to four steps: +## 配置您的项目去输出 .d.ts 文件 -- Add TypeScript to your dev dependencies -- Add a `tsconfig.json` to configure TypeScript -- Run the TypeScript compiler to generate the corresponding d.ts files for JS files -- (optional) Edit your package.json to reference the types +要在项目中添加 .d.ts 文件的构建,最多需要执行四个步骤: -### Adding TypeScript +- 添加 TypeScript 到您的开发依赖 +- 添加一个 `tsconfig.json` 来配置 TypeScript +- 运行 TypeScript 编译器来生成 JS 文件的 d.ts 文件 +- (可选) 编辑 package.json 来指定类型文件 -You can learn how to do this in our [installation page](/download). +### 添加 TypeScript -### TSConfig +您可以在我们的 [安装页面](/download) 中学会如何添加。 -The TSConfig is a jsonc file which configures both your compiler flags, and declare where to find files. -In this case, you will want a file like the following: +### TSConfig +TSConfig 是一份 jsonc 文件,其中配置了您的编译器标记,已经申明从哪里查找文件。 +在本例中,您将需要一个如下所示的文件: ```jsonc tsconfig { @@ -52,37 +52,39 @@ In this case, you will want a file like the following: } ``` -You can learn more about the options in the [tsconfig reference](/tsconfig). -An alternative to using a TSConfig file is the CLI, this is the same behavior as a CLI command. +您可以在 [tsconfig 参考](/tsconfig) 学习更多配置。 +另一个使用 TSConfig 的选择既是 CLI,它与 CLI 指令的行为一样。 ```sh npx -p typescript tsc src/**/*.js --declaration --allowJs --emitDeclarationOnly --outDir types ``` -## Run the compiler +## 运行编译器 + +您可以在我们的 [安装页面](/download) 中学会如何操作。 -You can learn how to do this in our [installation page](/download). + You want to make sure these files are included in your package if you have the files in your project's `.gitignore`. -## Editing the package.json +## 编辑 package.json -TypeScript replicates the node resolution for modules in a `package.json`, with an additional step for finding .d.ts files. -Roughly, the resolution will first check the optional `"types"` field, then the `"main"` field, and finally will try `index.d.ts` in the root. +TypeScript 复制了 `package.json` 中模块的节点解析,另外还有一个查找 .d.ts 文件的步骤。 +大致上,解析将从一个可选的 `"types"` 开始检查,之后是 `"main"` 字段,之后尝试查找项目根目录下的 `index.d.ts` 。 -| Package.json | Location of default .d.ts | +| Package.json | .d.ts 的默认位置 | | :------------------------ | :----------------------------- | -| No "types" field | checks "main", then index.d.ts | +| 无 "types" 字段 | 检查 "main", 然后是 index.d.ts | | "types": "main.d.ts" | main.d.ts | | "types": "./dist/main.js" | ./dist/main.d.ts | -If absent, then "main" is used +如果缺失, 就找 "main" 字段 -| Package.json | Location of default .d.ts | +| Package.json | .d.ts 的默认位置 | | :----------------------- | :------------------------ | -| No "main" field | index.d.ts | +| 无 "main" 字段 | index.d.ts | | "main":"index.js" | index.d.ts | | "main":"./dist/index.js" | ./dist/index.d.ts | ## Tips -If you'd like to write tests for your .d.ts files, try [tsd](https://github.com/SamVerschueren/tsd). +如果您想为您的 .d.ts 文件编写测试,试试这个 [tsd](https://github.com/SamVerschueren/tsd). From 7bae4a852fe48cefd896f074de23a456f13042fb Mon Sep 17 00:00:00 2001 From: zhouLion Date: Wed, 8 Sep 2021 23:24:37 +0800 Subject: [PATCH 04/15] ZH translations: javascript sections --- .../zh/javascript/Intro to JS with TS.md | 47 +++--- .../Type Checking JavaScript Files.md | 142 +++++++++--------- 2 files changed, 94 insertions(+), 95 deletions(-) diff --git a/docs/documentation/zh/javascript/Intro to JS with TS.md b/docs/documentation/zh/javascript/Intro to JS with TS.md index 4ebf0f5a..eda67338 100644 --- a/docs/documentation/zh/javascript/Intro to JS with TS.md +++ b/docs/documentation/zh/javascript/Intro to JS with TS.md @@ -1,31 +1,30 @@ --- title: JS Projects Utilizing TypeScript layout: docs -permalink: /docs/handbook/intro-to-js-ts.html -oneline: How to add type checking to JavaScript files using TypeScript +permalink: /zh/docs/handbook/intro-to-js-ts.html +oneline: 如何使用 TypeScript 给 JavaScript 文件添加类型检查 translatable: true --- -The type system in TypeScript has different levels of strictness when working with a codebase: +在不同代码库中,TypeScript 的类型系统有不同级别的严格性: +- 仅基于 JavaScript 代码推断的类型系统 +- 在 JavaScript 中 [通过 JSDoc](/docs/handbook/jsdoc-supported-types.html) 增加类型 +- 在 JavaScript 文件中使用 `// @ts-check` +- TypeScript 代码 +- TypeScript 代码,其 [`strict`](/tsconfig#strict) 设置为开启 -- A type-system based only on inference with JavaScript code -- Incremental typing in JavaScript [via JSDoc](/docs/handbook/jsdoc-supported-types.html) -- Using `// @ts-check` in a JavaScript file -- TypeScript code -- TypeScript with [`strict`](/tsconfig#strict) enabled +每一步都代表着向更安全的类型系统的迈进,但并非每个项目都需要这种级别的验证。 +## 使用 JavaScript 的 TypeScript -Each step represents a move towards a safer type-system, but not every project needs that level of verification. +就是当你使用的一个编辑器,它使用 TypeScript 来提供如自动补全,标识跳转的工具,还有像重命名这样的重构工具。 +在 [首页](/) 有一个自带 TypeScript 插件的编辑器清单。 -## TypeScript with JavaScript +## 在 JS 中通过 JSDoc 提供类型提示 -This is when you use an editor which uses TypeScript to provide tooling like auto-complete, jump to symbol and refactoring tools like rename. -The [homepage](/) has a list of editors which have TypeScript plugins. - -## Providing Type Hints in JS via JSDoc - -In a `.js` file, types can often be inferred. When types can't be inferred, they can be specified using JSDoc syntax. +在一个 `.js` 文件中,类型时通常是可以被推断的。当类型不能被推断时,他们也可以使用 JSDoc 语法加以指定。 JSDoc annotations come before a declaration will be used to set the type of that declaration. For example: +JSDoc 注释出现在声明之前,将用于设置该声明的类型。例如: ```js twoslash /** @type {number} */ @@ -35,12 +34,13 @@ x = 0; // OK x = false; // OK?! ``` -You can find the full list of supported JSDoc patterns [in JSDoc Supported Types](/docs/handbook/jsdoc-supported-types.html). +您可以在 [受 JSDoc 支持的类型](/docs/handbook/jsdoc-supported-types.html) 中找到 JSDoc 所支持的模式的完整清单。 ## `@ts-check` -The last line of the previous code sample would raise an error in TypeScript, but it doesn't by default in a JS project. -To enable errors in your JavaScript files add: `// @ts-check` to the first line in your `.js` files to have TypeScript raise it as an error. +上面代码示例中的最后一行,在 TypeScript 中会引发的报错,不过默认在 JS 项目中却不会。 +要使其在您的 JavaScript 中也报错,请添加: `// @ts-check` 到您的 `.js` 文件的第一行,让 TypeScript 去引发该错误的触发。 + ```js twoslash // @ts-check @@ -52,10 +52,11 @@ x = 0; // OK x = false; // Not OK ``` -If you have a lot of JavaScript files you want to add errors to then you can switch to using a [`jsconfig.json`](/docs/handbook/tsconfig-json.html). -You can skip checking some files by adding a `// @ts-nocheck` comment to files. +如果您有大量的 JavaScript 文件,您若想添加错误提示,那么您可以转为使用 [`jsconfig.json`](/docs/handbook/tsconfig-json.html)。 +您可以通过给文件添加 `// @ts-nocheck` 注释来跳过个别文件的检查。 + +TypeScript 有时会有您意料之外的报错,这种情形下您可以通过在上一行添加 `// @ts-ignore` 或者 `// @ts-expect-error` 来忽略这些报错。 -TypeScript may offer you errors which you disagree with, in those cases you can ignore errors on specific lines by adding `// @ts-ignore` or `// @ts-expect-error` on the preceding line. ```js twoslash // @ts-check @@ -67,4 +68,4 @@ x = 0; // OK x = false; // Not OK ``` -To learn more about how JavaScript is interpreted by TypeScript read [How TS Type Checks JS](/docs/handbook/type-checking-javascript-files.html) +要学习有关如何使用 TypeScript 解释 JavaScript,请参阅 [TS 类型如何检查 JS](/docs/handbook/type-checking-javascript-files.html) diff --git a/docs/documentation/zh/javascript/Type Checking JavaScript Files.md b/docs/documentation/zh/javascript/Type Checking JavaScript Files.md index cfcb2f34..95257937 100644 --- a/docs/documentation/zh/javascript/Type Checking JavaScript Files.md +++ b/docs/documentation/zh/javascript/Type Checking JavaScript Files.md @@ -1,20 +1,20 @@ --- title: Type Checking JavaScript Files layout: docs -permalink: /docs/handbook/type-checking-javascript-files.html -oneline: How to add type checking to JavaScript files using TypeScript +permalink: /zh/docs/handbook/type-checking-javascript-files.html +oneline: 如何使用 TypeScript 给 JavaScript 文件添加类型检查 --- -Here are some notable differences on how checking works in `.js` files compared to `.ts` files. +与 `.ts` 文件相比较,`.js` 文件的检查机制有一些明显的区别。 -## Properties are inferred from assignments in class bodies +## 属性是从类主体中的赋值推断出来的 -ES2015 does not have a means for declaring properties on classes. Properties are dynamically assigned, just like object literals. +ES2015 没有方法在类里面声明其属性。属性是动态赋值的,就像对象字面量。 -In a `.js` file, the compiler infers properties from property assignments inside the class body. -The type of a property is the type given in the constructor, unless it's not defined there, or the type in the constructor is undefined or null. -In that case, the type is the union of the types of all the right-hand values in these assignments. -Properties defined in the constructor are always assumed to exist, whereas ones defined just in methods, getters, or setters are considered optional. +在 `.js` 文件中,编译器从类主体中的属性赋值推断属性。 +属性的类型就是构造函数中所赋予的类型,除非在那里没有指定,或者在构造函数中指定的是 undefined 或者 null。 +因此,类型是这些赋值中所有右侧值的类型的并集。 +在构造函数中被定义的属性总是被设定为存在,而那些定义在方法、getters 或者 setters 中的就被看作是可选的。 ```js twoslash // @checkJs @@ -26,18 +26,18 @@ class C { } method() { this.constructorOnly = false; - this.constructorUnknown = "plunkbat"; // ok, constructorUnknown is string | undefined - this.methodOnly = "ok"; // ok, but methodOnly could also be undefined + this.constructorUnknown = "plunkbat"; // 没问题,constructorUnknown 的类型是 string | undefined + this.methodOnly = "ok"; // 没问题,但是 methodOnly 的类型依然是 undefined } method2() { - this.methodOnly = true; // also, ok, methodOnly's type is string | boolean | undefined + this.methodOnly = true; // 也没有问题, methodOnly 的类型是 string | boolean | undefined } } ``` -If properties are never set in the class body, they are considered unknown. -If your class has properties that are only read from, add and then annotate a declaration in the constructor with JSDoc to specify the type. -You don't even have to give a value if it will be initialised later: +如果属性从来没有在类主体中设置过,那他们被认定为 unknown。 +如果您的类中具有只能读取的属性,请在构造函数中添加声明,然后使用 JSDoc 对其进行注释,以指定类型。 +如果以后才会对其进行初始化,您甚至不必给出值: ```js twoslash // @checkJs @@ -56,11 +56,11 @@ c.prop = 0; // OK c.count = "string"; ``` -## Constructor functions are equivalent to classes +## 构造函数与类是等同的 -Before ES2015, Javascript used constructor functions instead of classes. -The compiler supports this pattern and understands constructor functions as equivalent to ES2015 classes. -The property inference rules described above work exactly the same way. +在 ES2015 之前,JavaScript 是使用构造器函数而非类。 +编译器支持这种模式,且将构造器函数理解为等同于 ES2015 的类。 +属性的推断规则与上述的方式完全相同。 ```js twoslash // @checkJs @@ -75,36 +75,35 @@ C.prototype.method = function () { }; ``` -## CommonJS modules are supported +## 支持 CommonJS 模块 -In a `.js` file, TypeScript understands the CommonJS module format. -Assignments to `exports` and `module.exports` are recognized as export declarations. -Similarly, `require` function calls are recognized as module imports. For example: +在一个 `.js` 文件中,TypeScript 能理解 CommonJS 模块格式。 +`exports` 与 `module.exports` 的赋值被认定为 export 声明。 +类似的, `require` 方法的调用,被视为模块引入。例如: ```js -// same as `import module "fs"` +// 等同 `import module "fs"` const fs = require("fs"); -// same as `export function readFile` +// 等同 `export function readFile` module.exports.readFile = function (f) { return fs.readFileSync(f); }; ``` -The module support in Javascript is much more syntactically forgiving than TypeScript's module support. -Most combinations of assignments and declarations are supported. +在语法上,Javascript 中的模块支持,比 TypeScript 的更具宽松。 +其支持大多数赋值和声明的组合。 +## 类型,函数和对象字面量都是命名空间 -## Classes, functions, and object literals are namespaces - -Classes are namespaces in `.js` files. -This can be used to nest classes, for example: +在 `.js` 文件中,类型是命名空间。 +它可以用来嵌套类型,比如: ```js twoslash class C {} C.D = class {}; ``` -And, for pre-ES2015 code, it can be used to simulate static methods: +并且,对于 ES2015 之前的代码,它可以用来模仿静态方法: ```js twoslash function Outer() { @@ -118,7 +117,7 @@ Outer.Inner = function () { Outer.Inner(); ``` -It can also be used to create simple namespaces: +它也可以用来创建一个简单的命名空间: ```js twoslash var ns = {}; @@ -128,7 +127,7 @@ ns.func = function () {}; ns; ``` -Other variants are allowed as well: +也支持其它的变体: ```js twoslash // IIFE @@ -146,21 +145,20 @@ var assign = assign.extra = 1; ``` -## Object literals are open-ended +## 对象字面量是开放的 -In a `.ts` file, an object literal that initializes a variable declaration gives its type to the declaration. -No new members can be added that were not specified in the original literal. -This rule is relaxed in a `.js` file; object literals have an open-ended type (an index signature) that allows adding and looking up properties that were not defined originally. -For instance: +一个 `.ts` 文件中,一个初始化了变量声明的对象字面量,即赋予了其声明的类型。 +不允许加入原始字面量中所未指定的新成员。 +该规则在 `.js` 文件中变为宽松了;对象字面量有这开放的类型(索引签名),其允许添加和查看最初没有被定义的属性。 +比如: ```js twoslash var obj = { a: 1 }; obj.b = 2; // Allowed ``` -Object literals behave as if they have an index signature `[x:string]: any` that allows them to be treated as open maps instead of closed objects. - -Like other special JS checking behaviors, this behavior can be changed by specifying a JSDoc type for the variable. For example: +对象字面量的这一行为就好像其有一个索引签名 `[x:string]: any`,这样使其作为开放的 map 对待,而非封闭对象。 +就像其他特殊的 JS 检查行为,这些行为可以通过为其变量指定一个 JSDoc 类型而改变。比如: ```js twoslash // @checkJs @@ -170,11 +168,11 @@ var obj = { a: 1 }; obj.b = 2; ``` -## null, undefined, and empty array initializers are of type any or any[] +## null、undefined 和空数组初始化为 any 或者 any[] 类型 -Any variable, parameter or property that is initialized with null or undefined will have type any, even if strict null checks is turned on. -Any variable, parameter or property that is initialized with [] will have type any[], even if strict null checks is turned on. -The only exception is for properties that have multiple initializers as described above. +任何变量、参数或者属性,一旦被初始化为 `null` 或者 `undefined`,其类型就会为 any,即使开启了严格的 `null` 检查。 +任何变量、参数或者属性,一旦被初始化为 `[]` ,其类型将为 `any[]`,即使开启了严格的 `null` 检查。 +唯一的例外是如上所述具有多个初始值设定项的属性。 ```js twoslash function Foo(i = null) { @@ -189,14 +187,14 @@ foo.l.push(foo.i); foo.l.push("end"); ``` -## Function parameters are optional by default +## 函数的参数默认是可选的 -Since there is no way to specify optionality on parameters in pre-ES2015 Javascript, all function parameters in `.js` file are considered optional. -Calls with fewer arguments than the declared number of parameters are allowed. +由于在 ES2015 之前的 JavaScript中,没有办法制定参数的可选性,所以 `.js` 所有的方法的参数都被视为可选的。 +调用时传递的参数少于所声明的个数,是被允许的。 -It is important to note that it is an error to call a function with too many arguments. +需要注意的是,调用时传递过多的参数是错误的。 -For instance: +比如: ```js twoslash // @checkJs @@ -206,13 +204,13 @@ function bar(a, b) { console.log(a + " " + b); } -bar(1); // OK, second argument considered optional +bar(1); // 没问题,第二个参数被视为可选 bar(1, 2); -bar(1, 2, 3); // Error, too many arguments +bar(1, 2, 3); // 报错了,传递过多的参数 ``` -JSDoc annotated functions are excluded from this rule. -Use JSDoc optional parameter syntax (`[` `]`) to express optionality. e.g.: +JSDoc 注释的函数不在此规则之中。 +使用 JSDoc 可选参数语法(`[` `]`)来表示可选性。比如: ```js twoslash /** @@ -228,9 +226,9 @@ function sayHello(somebody) { sayHello(); ``` -## Var-args parameter declaration inferred from use of `arguments` +## 使用了 `arguments` 的 Var-args 参数声明推断 -A function whose body has a reference to the `arguments` reference is implicitly considered to have a var-arg parameter (i.e. `(...arg: any[]) => any`). Use JSDoc var-arg syntax to specify the type of the arguments. +如果一个函数体引用了 `arguments` 引用,则隐式认为该函数具有 var-arg 参数(就像`(...arg: any[]) => any`)。使用 JSDoc 的 var-arg 语法来指定参数的类型。 ```js twoslash /** @param {...number} args */ @@ -243,14 +241,14 @@ function sum(/* numbers */) { } ``` -## Unspecified type parameters default to `any` +## 未指定类型的参数被视为 `any` 类型 -Since there is no natural syntax for specifying generic type parameters in Javascript, an unspecified type parameter defaults to `any`. +由于没有在 JavaScript 中没有指定泛型类型参数的自然语法,所以为制定类型的参数默认为 `any`。 -### In extends clause +### 在 extends 子句中 -For instance, `React.Component` is defined to have two type parameters, `Props` and `State`. -In a `.js` file, there is no legal way to specify these in the extends clause. By default the type arguments will be `any`: +举个例子, `React.Component` 被定义为有两个参数,为 `Props` 和 `State`。 +在 `.js` 文件中,没有合理的方式,在扩展子句中去指定它们,于是这两个参数就为 `any`: ```js import { Component } from "react"; @@ -262,7 +260,7 @@ class MyComponent extends Component { } ``` -Use JSDoc `@augments` to specify the types explicitly. for instance: +使用 `@augments` 来明确指定类型。比如: ```js import { Component } from "react"; @@ -277,27 +275,27 @@ class MyComponent extends Component { } ``` -### In JSDoc references +### 在JSDoc 参照中 -An unspecified type argument in JSDoc defaults to any: +JSDoc 中未指定类型的参数默认为 any: ```js twoslash /** @type{Array} */ var x = []; -x.push(1); // OK -x.push("string"); // OK, x is of type Array +x.push(1); // 没问题 +x.push("string"); // 没问题, x 的类型为 Array /** @type{Array.} */ var y = []; -y.push(1); // OK -y.push("string"); // Error, string is not assignable to number +y.push(1); // 没问题 +y.push("string"); // 报错, string 不能飞配给 number 类型 ``` -### In function calls +### 在函数调用中 -A call to a generic function uses the arguments to infer the type parameters. Sometimes this process fails to infer any types, mainly because of lack of inference sources; in these cases, the type parameters will default to `any`. For example: +泛型函数的调用,使用泛型参数来推断类型参数。有的时候这一过程无法推断出任何类型,主要是因为缺乏推断来源;因此,类型参数将默认设为 `any`。比如: ```js var p = new Promise((resolve, reject) => { @@ -307,4 +305,4 @@ var p = new Promise((resolve, reject) => { p; // Promise; ``` -To learn all of the features available in JSDoc, see [the reference](/docs/handbook/jsdoc-supported-types.html). +了解JSDoc中的所有可用功能,请参阅 [此手册](/docs/handbook/jsdoc-supported-types.html)。 From f32dc9f150c130df21a714ee484814bca775eaf2 Mon Sep 17 00:00:00 2001 From: zhouLion Date: Thu, 9 Sep 2021 08:24:40 +0800 Subject: [PATCH 05/15] ZH transition: translate coditional types --- .../Type Manipulation/Conditional Types.md | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md index e801811c..84135bb8 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md @@ -1,13 +1,13 @@ --- title: Conditional Types layout: docs -permalink: /docs/handbook/2/conditional-types.html -oneline: "Create types which act like if statements in the type system." +permalink: /zh/docs/handbook/2/conditional-types.html +oneline: "在类型系统中像 if 语句那样的类型" --- -At the heart of most useful programs, we have to make decisions based on input. -JavaScript programs are no different, but given the fact that values can be easily introspected, those decisions are also based on the types of the inputs. -_Conditional types_ help describe the relation between the types of inputs and outputs. +在最有用的程序中,我们必须根据输入做出决定。 +JavaScript 程序也不例外,但鉴于值可以很容易地进行内省,这些决策也基于输入的类型。 +_条件类型_ 帮助描述输入和输出类型之间的关系。 ```ts twoslash interface Animal { @@ -24,7 +24,7 @@ type Example2 = RegExp extends Animal ? number : string; // ^? ``` -Conditional types take a form that looks a little like conditional expressions (`condition ? trueExpression : falseExpression`) in JavaScript: +条件类型采用的这种形式看起来有点像 JavaScript 中的条件表达式 (`condition ? trueExpression : falseExpression`) : ```ts twoslash type SomeType = any; @@ -35,13 +35,12 @@ type Stuff = // ---cut--- SomeType extends OtherType ? TrueType : FalseType; ``` +当 `extends` 左侧的类型可以分配给右侧这个是,那么您将获取第一个分支上的类型(即「true」分支);否则您将获取在后面分支上的类型(即「false」分支)。 -When the type on the left of the `extends` is assignable to the one on the right, then you'll get the type in the first branch (the "true" branch); otherwise you'll get the type in the latter branch (the "false" branch). +从上面的例子来看,条件类型可能不会立即变得有用 -- 我们可以告诉自己 `Dog extensed Animal` 是否成立,然后选择 `number` 或 `string`! +但是条件类型的威力来自于将它们与泛型一起使用。 -From the examples above, conditional types might not immediately seem useful - we can tell ourselves whether or not `Dog extends Animal` and pick `number` or `string`! -But the power of conditional types comes from using them with generics. - -For example, let's take the following `createLabel` function: +举个例子,我们来看下面的 `createLabel` 函数: ```ts twoslash interface IdLabel { @@ -58,13 +57,12 @@ function createLabel(nameOrId: string | number): IdLabel | NameLabel { throw "unimplemented"; } ``` +`createLabel` 函数的这些重载,描述的一个单独的 JavaScript 函数,此函数根据输入的类型有不同的选项。 注意这几点: -These overloads for createLabel describe a single JavaScript function that makes a choice based on the types of its inputs. Note a few things: - -1. If a library has to make the same sort of choice over and over throughout its API, this becomes cumbersome. -2. We have to create three overloads: one for each case when we're _sure_ of the type (one for `string` and one for `number`), and one for the most general case (taking a `string | number`). For every new type `createLabel` can handle, the number of overloads grows exponentially. +1. 如果一个库必须在整个 API 中反复做出相同的选项,那么这将变得很麻烦。 +2. 我们不得不创建三个重载:一个是我们已经确定类型的各个情形 (其一是 `string` ,另一个是 `number`),然后另一个是最通用的情形 (接收一个 `string | number`)。对于 `createLabel` 可以处理的每一种新类型,重载的数量都会呈指数增长。 -Instead, we can encode that logic in a conditional type: +代之,我们可以通过条件类型来编写这段逻辑: ```ts twoslash interface IdLabel { @@ -79,7 +77,7 @@ type NameOrId = T extends number : NameLabel; ``` -We can then use that conditional type to simplify our overloads down to a single function with no overloads. +之后,我们可以使用该条件类型将重载简化为一个没有重载的函数。 ```ts twoslash interface IdLabel { @@ -106,20 +104,20 @@ let c = createLabel(Math.random() ? "hello" : 42); // ^? ``` -### Conditional Type Constraints +### 条件类型约束 -Often, the checks in a conditional type will provide us with some new information. -Just like with narrowing with type guards can give us a more specific type, the true branch of a conditional type will further constrain generics by the type we check against. +通常,条件类型中的检查会为我们提供一些新信息。 +就像使用类型保护,缩小范围可以为我们提供更具体的类型一样,条件类型的 true 分支将通过我们检查的类型进一步约束泛型。 -For example, let's take the following: +举例, 我们看下面代码: ```ts twoslash // @errors: 2536 type MessageOf = T["message"]; ``` -In this example, TypeScript errors because `T` isn't known to have a property called `message`. -We could constrain `T`, and TypeScript would no longer complain: +在这个示例中,TypeScript 报错了,因为 `T` 无法判断其有名为 `message` 的属性。 +我们可以约束 `T`,TypeScript 就不再报错了: ```ts twoslash type MessageOf = T["message"]; @@ -132,8 +130,9 @@ type EmailMessageContents = MessageOf; // ^? ``` -However, what if we wanted `MessageOf` to take any type, and default to something like `never` if a `message` property isn't available? -We can do this by moving the constraint out and introducing a conditional type: +然而,我们如果想要 `MessageOf` 能接受任意的类型,并且如果其没有 `message` 属性,那就是一个默认类型,就像 `never` ,这该怎么办呢? + +我们可以通过将约束移出并引入条件类型来实现这一点: ```ts twoslash type MessageOf = T extends { message: unknown } ? T["message"] : never; @@ -153,9 +152,9 @@ type DogMessageContents = MessageOf; // ^? ``` -Within the true branch, TypeScript knows that `T` _will_ have a `message` property. +在 true 分支中, TypeScript 明白 `T` _将_ 有 `message` 属性。 -As another example, we could also write a type called `Flatten` that flattens array types to their element types, but leaves them alone otherwise: +作为另一个示例,我们还可以编写一个名为 `Flatten` 的类型,将数组类型展平为其元素类型,但在其他情况下不使用它们: ```ts twoslash type Flatten = T extends any[] ? T[number] : T; @@ -169,26 +168,27 @@ type Num = Flatten; // ^? ``` -When `Flatten` is given an array type, it uses an indexed access with `number` to fetch out `string[]`'s element type. -Otherwise, it just returns the type it was given. +当 `Flatten` 接收一个数组类型,它通过使用 `number` 索引访问以获取 `string[]` 的元素类型。 +否则,它仅返回传入给它的类型。 -### Inferring Within Conditional Types +### 条件类型内的推断 -We just found ourselves using conditional types to apply constraints and then extract out types. -This ends up being such a common operation that conditional types make it easier. +我们只是发现自己使用条件类型来应用约束,然后提取类型。 +这是一个非常常见的操作,条件类型使它变得更容易。 -Conditional types provide us with a way to infer from types we compare against in the true branch using the `infer` keyword. -For example, we could have inferred the element type in `Flatten` instead of fetching it out "manually" with an indexed access type: +条件类型为我们提供了一种从 `true` 分支中比较的类型中进行推断的方法,就是使用 `infer` 关键字。 +例如,我们可以推断出在 `Flatten` 中元素的类型,而不是用索引访问类型「手动」获取它: ```ts twoslash type Flatten = Type extends Array ? Item : Type; ``` -Here, we used the `infer` keyword to declaratively introduce a new generic type variable named `Item` instead of specifying how to retrieve the element type of `T` within the true branch. -This frees us from having to think about how to dig through and probing apart the structure of the types we're interested in. +这里,我们使用 `infer` 关键词去声明性地引入一个新的泛型变量 `Item`,而不是指定如何如何在 true 分支中去会 `T` 元素类型。 +这使得我们不必考虑怎样去发掘和探究我们感兴趣的类型结构了。 + -We can write some useful helper type aliases using the `infer` keyword. -For example, for simple cases, we can extract the return type out from function types: +运用 `infer` 关键词,我们可以写一些实用的辅助类型别称。 +例如,对于简单的场景,我们可以从函数类型中提取出返回类型。 ```ts twoslash type GetReturnType = Type extends (...args: never[]) => infer Return @@ -205,7 +205,7 @@ type Bools = GetReturnType<(a: boolean, b: boolean) => boolean[]>; // ^? ``` -When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the _last_ signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types. +当从一个具有多个调用签名的类型(比如一个重载函数的类型)中进行推断时,是从 _最后_ 一项签名中(这项可能是最宽泛的情形)做推断的。无法基于参数类型列表来执行重载的解析。 ```ts twoslash declare function stringOrNum(x: string): number; @@ -216,16 +216,16 @@ type T1 = ReturnType; // ^? ``` -## Distributive Conditional Types +## 分配条件类型 -When conditional types act on a generic type, they become _distributive_ when given a union type. -For example, take the following: +当条件类型作用于泛型类型时,当给定一个联合类型时,它们就变成了 _分配的_。 +例如,看下面: ```ts twoslash type ToArray = Type extends any ? Type[] : never; ``` -If we plug a union type into `ToArray`, then the conditional type will be applied to each member of that union. +如果我们将一个联合类型插入 `ToArray`,那么条件类型将应用于该联合类型中的每个成员。 ```ts twoslash type ToArray = Type extends any ? Type[] : never; @@ -234,7 +234,7 @@ type StrArrOrNumArr = ToArray; // ^? ``` -What happens here is that `StrArrOrNumArr ` distributes on: +然而 `StrArrOrNumArr` 却是这样分配的: ```ts twoslash type StrArrOrNumArr = @@ -242,7 +242,7 @@ type StrArrOrNumArr = string | number; ``` -and maps over each member type of the union, to what is effectively: +把联合类型中的每个成员类型映射进来,这样才能生效: ```ts twoslash type ToArray = Type extends any ? Type[] : never; @@ -251,7 +251,7 @@ type StrArrOrNumArr = ToArray | ToArray; ``` -which leaves us with: +就是这样的: ```ts twoslash type StrArrOrNumArr = @@ -259,13 +259,13 @@ type StrArrOrNumArr = string[] | number[]; ``` -Typically, distributivity is the desired behavior. -To avoid that behavior, you can surround each side of the `extends` keyword with square brackets. +通常,分配性是预期的行为。 +为了避免这种行为,可以用方括号括住 extends 关键字的每一侧。 ```ts twoslash type ToArrayNonDist = [Type] extends [any] ? Type[] : never; -// 'StrArrOrNumArr' is no longer a union. +// 'StrArrOrNumArr' 就不在是联合类型。 type StrArrOrNumArr = ToArrayNonDist; // ^? ``` From be5361ba8a47d7de6138c04d863f51b088a29f22 Mon Sep 17 00:00:00 2001 From: zhouLion Date: Thu, 9 Sep 2021 13:26:20 +0800 Subject: [PATCH 06/15] ZH transitions: Make semantic smoothness --- .../zh/handbook-v2/Type Manipulation/Conditional Types.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md index 84135bb8..bcbacc23 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Conditional Types.md @@ -234,7 +234,7 @@ type StrArrOrNumArr = ToArray; // ^? ``` -然而 `StrArrOrNumArr` 却是这样分配的: +然后 `StrArrOrNumArr` 却是这样分配类型的: ```ts twoslash type StrArrOrNumArr = @@ -242,7 +242,7 @@ type StrArrOrNumArr = string | number; ``` -把联合类型中的每个成员类型映射进来,这样才能生效: +需要把联合类型中的每个成员类型都映射进来,这样才能生效: ```ts twoslash type ToArray = Type extends any ? Type[] : never; @@ -251,7 +251,7 @@ type StrArrOrNumArr = ToArray | ToArray; ``` -就是这样的: +就像这样的: ```ts twoslash type StrArrOrNumArr = From b8e983d941c685ee5339fdbaa774931ba32b9cd1 Mon Sep 17 00:00:00 2001 From: zhouLion Date: Thu, 9 Sep 2021 23:38:35 +0800 Subject: [PATCH 07/15] ZH translation: trans handbook --- .../zh/handbook-v2/The Handbook.md | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/The Handbook.md b/docs/documentation/zh/handbook-v2/The Handbook.md index 4d46032f..8b022bbe 100644 --- a/docs/documentation/zh/handbook-v2/The Handbook.md +++ b/docs/documentation/zh/handbook-v2/The Handbook.md @@ -1,59 +1,60 @@ --- title: The TypeScript Handbook layout: docs -permalink: /docs/handbook/intro.html -oneline: Your first step to learn TypeScript +permalink: /zh/docs/handbook/intro.html +oneline: 初探 TypeScript handbook: "true" --- -## About this Handbook +## 关于这本手册 -Over 20 years after its introduction to the programming community, JavaScript is now one of the most widespread cross-platform languages ever created. Starting as a small scripting language for adding trivial interactivity to webpages, JavaScript has grown to be a language of choice for both frontend and backend applications of every size. While the size, scope, and complexity of programs written in JavaScript has grown exponentially, the ability of the JavaScript language to express the relationships between different units of code has not. Combined with JavaScript's rather peculiar runtime semantics, this mismatch between language and program complexity has made JavaScript development a difficult task to manage at scale. +JavaScript 被引入编程社区 20 多年后,现在已成为有史以来最广泛使用的跨平台语言之一。JavaScript 最初是一种小型脚本语言,用于为网页添加零星的交互性,现在已成为各种规模的前端和后端应用程序的首选语言。随着使用 JavaScript 编写的程序的规模、领域和复杂度指数级增长,其根本不具备能力来表达不同单元代码之间的相关性。再加上 JavaScript 特有的运行时语义,这种语言与程序复杂性之间的不搭调,让 JavaScript 的开发成为了难以进行大规模管理的任务。 -The most common kinds of errors that programmers write can be described as type errors: a certain kind of value was used where a different kind of value was expected. This could be due to simple typos, a failure to understand the API surface of a library, incorrect assumptions about runtime behavior, or other errors. The goal of TypeScript is to be a static typechecker for JavaScript programs - in other words, a tool that runs before your code runs (static) and ensures that the types of the program are correct (typechecked). +程序员写代码最典型的错误可以称为类型错误:一个明确类型的值被用在了期望是别的类型的值的地方。这可能只是一个简单的打字疏误,对库外层 API 的误解,对运行时行为的不当猜测,抑或别的错误。TypeScript 的目的就是成为 JavaScript 程序的静态类型检查器 - 换而言之,是一个在您的代码运行(静态的)之前运行的,以确保程序的类型时正确的工具(已类型检查的)。 -If you are coming to TypeScript without a JavaScript background, with the intention of TypeScript being your first language, we recommend you first start reading the documentation on either the [Microsoft Learn JavaScript tutorial](https://docs.microsoft.com/javascript/) or read [JavaScript at the Mozilla Web Docs](https://developer.mozilla.org/docs/Web/JavaScript/Guide). -If you have experience in other languages, you should be able to pick up JavaScript syntax quite quickly by reading the handbook. +如果您是在没有 JavaScript 背景下接触 TypeScript 的,意图让 TypeScript 成为您的第一个开发语言,我们推荐您首先阅读这些文档 [Microsoft Learn JavaScript tutorial](https://docs.microsoft.com/javascript/) 或者 [JavaScript at the Mozilla Web Docs](https://developer.mozilla.org/docs/Web/JavaScript/Guide)。 +如果您有其他语言的开发经验,您应该通过阅读本手册就能来非常快速地掌握 JavaScript 语法 -## How is this Handbook Structured +## 本操作手册的结构 -The handbook is split into two sections: +本操作手册分为两个章节: -- **The Handbook** +- **手册** - The TypeScript Handbook is intended to be a comprehensive document that explains TypeScript to everyday programmers. You can read the handbook by going from top to bottom in the left-hand navigation. + TypeScript 手册有意作为一份综合性的文档,来向日常程序员们解释 TypeScript。您可以在左侧导航栏中从上到下阅读手册。 - You should expect each chapter or page to provide you with a strong understanding of the given concepts. The TypeScript Handbook is not a complete language specification, but it is intended to be a comprehensive guide to all of the language's features and behaviors. + 你应该期望每一章或每一页都能让你对给定的概念有一个深刻的理解。TypeScript 手册不是一个完整的语言规范,但它旨在全面指导语言的所有特性和行为。 - A reader who completes the walkthrough should be able to: + 完成演练的读者应能够: - - Read and understand commonly-used TypeScript syntax and patterns - - Explain the effects of important compiler options - - Correctly predict type system behavior in most cases + - 阅读并理解常用的 TypeScript 语法和模式 + - 解释重要编译器选项的效果 + - 在大多数情况下,正确预测类型系统行为 - In the interests of clarity and brevity, the main content of the Handbook will not explore every edge case or minutiae of the features being covered. You can find more details on particular concepts in the reference articles. + 为了清晰和简洁起见,本手册的主要内容不会探讨所涵盖特征的每一个边缘情况或细节。您可以在参考文章中找到有关特定概念的更多详细信息。 -- **Reference Files** +- **参考文件** - The reference section below the handbook in the navigation is built to provide a richer understanding of how a particular part of TypeScript works. You can read it top-to-bottom, but each section aims to provide a deeper explanation of a single concept - meaning there is no aim for continuity. + 导航中手册下方的参考部分旨在更深入地了解 TypeScript 的特定部分是如何工作的。你可以自上而下地阅读,但每一部分的目的都是对一个概念进行更深入的解释——这意味着没有连续性的目标。 -### Non-Goals +### 非目标 -The Handbook is also intended to be a concise document that can be comfortably read in a few hours. Certain topics won't be covered in order to keep things short. +该手册也是一份简明的文件,可以在几个小时内轻松阅读。为了保持简短,某些主题将不会被涵盖。 -Specifically, the Handbook does not fully introduce core JavaScript basics like functions, classes, and closures. Where appropriate, we'll include links to background reading that you can use to read up on those concepts. +具体来说,该手册没有完全介绍核心 JavaScript 基础知识,如函数、类和闭包。在适当的情况下,我们将包括背景阅读的链接,您可以使用这些链接来阅读这些概念。 -The Handbook also isn't intended to be a replacement for a language specification. In some cases, edge cases or formal descriptions of behavior will be skipped in favor of high-level, easier-to-understand explanations. Instead, there are separate reference pages that more precisely and formally describe many aspects of TypeScript's behavior. The reference pages are not intended for readers unfamiliar with TypeScript, so they may use advanced terminology or reference topics you haven't read about yet. +本手册也无意取代语言规范。在某些情况下,边缘案例或行为的正式描述将被跳过,以支持更高层次、更容易理解的解释。相反,有单独的参考页,更精确和正式地描述TypeScript行为的许多方面。参考页不适用于不熟悉TypeScript的读者,因此它们可能会使用您尚未阅读过的高级术语或参考主题。 -Finally, the Handbook won't cover how TypeScript interacts with other tools, except where necessary. Topics like how to configure TypeScript with webpack, rollup, parcel, react, babel, closure, lerna, rush, bazel, preact, vue, angular, svelte, jquery, yarn, or npm are out of scope - you can find these resources elsewhere on the web. +最后,除了必要的地方,本手册不会介绍 TypeScript 如何与其他工具交互。诸如如何使用 webpack、rollup、packet、react、babel、closure、lerna、rush、bazel、preact、vue、angular、svelte、jquery、warn 或 npm 配置 TypeScript 等主题不在讨论范围之内-您可以在web上的其他地方找到这些资源。 + +## 入门 +在开始学习[基础知识](/docs/handbook/2/basic types.html)之前,我们建议先阅读以下介绍页面之一。这些介绍旨在强调 TypeScript 和您喜欢的编程语言之间的关键相似性和差异,并澄清这些语言特有的常见误解。 -## Get Started -Before getting started with [The Basics](/docs/handbook/2/basic-types.html), we recommend reading one of the following introductory pages. These introductions are intended to highlight key similarities and differences between TypeScript and your favored programming language, and clear up common misconceptions specific to those languages. - [TypeScript for New Programmers](/docs/handbook/typescript-from-scratch.html) - [TypeScript for JavaScript Programmers](/docs/handbook/typescript-in-5-minutes.html) - [TypeScript for OOP Programmers](/docs/handbook/typescript-in-5-minutes-oop.html) - [TypeScript for Functional Programmers](/docs/handbook/typescript-in-5-minutes-func.html) -Otherwise, jump to [The Basics](/docs/handbook/2/basic-types.html) or grab a copy in [Epub](/assets/typescript-handbook.epub) or [PDF](/assets/typescript-handbook.pdf) form. +否则跳转至 [The Basics](/docs/handbook/2/basic-types.html) 或者在[Epub](/assets/typescript-handbook.epub) 获取副本或者 [PDF](/assets/typescript-handbook.pdf) 形式。 From 688228ea53f813e1dfc30560c4d3a53e576e0136 Mon Sep 17 00:00:00 2001 From: zhouLion Date: Fri, 10 Sep 2021 13:42:33 +0800 Subject: [PATCH 08/15] ZH transitions: trans keyof keyword --- .../Type Manipulation/Keyof Type Operator.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Keyof Type Operator.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Keyof Type Operator.md index 4f2c09c4..46304ca7 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Keyof Type Operator.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Keyof Type Operator.md @@ -1,13 +1,13 @@ --- title: Keyof Type Operator layout: docs -permalink: /docs/handbook/2/keyof-types.html -oneline: "Using the keyof operator in type contexts." +permalink: /zh/docs/handbook/2/keyof-types.html +oneline: "在类型上下文里使用 keyof 关键字" --- -## The `keyof` type operator +## `keyof` 类型操作符 -The `keyof` operator takes an object type and produces a string or numeric literal union of its keys: +`keyof` 类型操作符接受一个对象类型,产出其 key 的字符或者数字的合集类型: ```ts twoslash type Point = { x: number; y: number }; @@ -15,7 +15,7 @@ type P = keyof Point; // ^? ``` -If the type has a `string` or `number` index signature, `keyof` will return those types instead: +如果这个类有一个 `string` 或者 `number` 索引签名,则 `keyof` 将返回这些类型: ```ts twoslash type Arrayish = { [n: number]: unknown }; @@ -27,6 +27,6 @@ type M = keyof Mapish; // ^? ``` -Note that in this example, `M` is `string | number` -- this is because JavaScript object keys are always coerced to a string, so `obj[0]` is always the same as `obj["0"]`. +注意,在本例中,`M` 是 `string | number` --这是因为 JavaScript 对象键总是强制为字符串,所以 `obj[0]` 总是与 `obj[“0”]` 相同。 -`keyof` types become especially useful when combined with mapped types, which we'll learn more about later. +`keyof` 类型特别适用于与映射类型组合,我们将在后面了解更多。 From a3fa378e72dac3c9ba22a76db9f7f1f6ee9ae23d Mon Sep 17 00:00:00 2001 From: zhouLion Date: Sat, 11 Sep 2021 07:58:01 +0800 Subject: [PATCH 09/15] ZH translation: Mapped Types --- .../Type Manipulation/Mapped Types.md | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md index ace109c0..64bb7b9f 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md @@ -1,13 +1,13 @@ --- title: Mapped Types layout: docs -permalink: /docs/handbook/2/mapped-types.html -oneline: "Generating types by re-using an existing type." +permalink: /zh/docs/handbook/2/mapped-types.html +oneline: "通过复用已有类型来生成类型。" --- -When you don't want to repeat yourself, sometimes a type needs to be based on another type. +当你不想重复你自己时,有时一个类型需要基于另一个类型。 -Mapped types build on the syntax for index signatures, which are used to declare the types of properties which has not been declared ahead of time: +映射类型基于索引签名的语法构建,它用于声明尚未提前声明的属性类型: ```ts twoslash type Horse = {}; @@ -22,7 +22,7 @@ const conforms: OnlyBoolsAndHorses = { }; ``` -A mapped type is a generic type which uses a union of `PropertyKey`s (frequently created [via a `keyof`](/docs/handbook/2/indexed-access-types.html)) to iterate through keys to create a type: +映射类型是一种泛型类型,它使用 `PropertyKey` 的联合(通常 [通过 `keyof`](/docs/handbook/2/indexed-access-types.html))来迭代键以创建类型: ```ts twoslash type OptionsFlags = { @@ -30,7 +30,7 @@ type OptionsFlags = { }; ``` -In this example, `OptionsFlags` will take all the properties from the type `Type` and change their values to be a boolean. +在此示例中,`OptionsFlags` 接收 `Type` 类型上所有的属性,并将它们的值转为 boolean。 ```ts twoslash type OptionsFlags = { @@ -46,14 +46,14 @@ type FeatureOptions = OptionsFlags; // ^? ``` -### Mapping Modifiers +### 映射修饰符 -There are two additional modifiers which can be applied during mapping: `readonly` and `?` which affect mutability and optionality respectively. +有两个附加修饰符可以在映射是应用到:`readonly` 和 `?` 分别作用于可变性和可选择性。 -You can remove or add these modifiers by prefixing with `-` or `+`. If you don't add a prefix, then `+` is assumed. +您可以通过前缀 `-` 来删除这些修饰符,或者用 `+` 增加它们。如果没有前缀,就默认为 `+`。 ```ts twoslash -// Removes 'readonly' attributes from a type's properties +// 从类型的属性中移除 'readonly' 标记 type CreateMutable = { -readonly [Property in keyof Type]: Type[Property]; }; @@ -68,7 +68,7 @@ type UnlockedAccount = CreateMutable; ``` ```ts twoslash -// Removes 'optional' attributes from a type's properties +// 从类型的属性中移除 'optional' 标记 type Concrete = { [Property in keyof Type]-?: Type[Property]; }; @@ -83,9 +83,9 @@ type User = Concrete; // ^? ``` -## Key Remapping via `as` +## 通过 `as` 重新映射键 -In TypeScript 4.1 and onwards, you can re-map keys in mapped types with an `as` clause in a mapped type: +在 TypeScript 4.1 及更高版本,您可以使用映射类型中的 `as` 子句重新映射映射类型中的键: ```ts type MappedTypeWithNewProperties = { @@ -93,7 +93,7 @@ type MappedTypeWithNewProperties = { } ``` -You can leverage features like [template literal types](/docs/handbook/2/template-literal-types.html) to create new property names from prior ones: +您可以利用 [模版字面量类型](/docs/handbook/2/template-literal-types.html) 等功能,从以前的属性名称创建新的属性名称: ```ts twoslash type Getters = { @@ -110,10 +110,10 @@ type LazyPerson = Getters; // ^? ``` -You can filter out keys by producing `never` via a conditional type: +您可以通过条件类型生成 `never` 来筛选出键: ```ts twoslash -// Remove the 'kind' property +// 移除 'kind' 属性 type RemoveKindField = { [Property in keyof Type as Exclude]: Type[Property] }; @@ -127,9 +127,9 @@ type KindlessCircle = RemoveKindField; // ^? ``` -### Further Exploration +### 未来探索 -Mapped types work well with other features in this type manipulation section, for example here is [a mapped type using a conditional type](/docs/handbook/2/conditional-types.html) which returns either a `true` or `false` depending on whether an object has the property `pii` set to the literal `true`: +映射类型与此类型操作部分中的其他功能配合得很好,例如,这里有 [使用条件类型的映射类型](/docs/handbook/2/conditional-types.html) 它返回 `true` 或 `false`,这取决于对象是否将属性 `pii` 设置为文字 `true`。 ```ts twoslash type ExtractPII = { From 5447e2941926559cfb3f517b97b0f5f0a614fbcb Mon Sep 17 00:00:00 2001 From: zhouLion Date: Sat, 11 Sep 2021 10:10:07 +0800 Subject: [PATCH 10/15] ZH translation: Typeof operator --- .../Type Manipulation/Typeof Type Operator.md | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md index a48674ed..0cc7b274 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Typeof Type Operator.md @@ -1,20 +1,20 @@ --- title: Typeof Type Operator layout: docs -permalink: /docs/handbook/2/typeof-types.html -oneline: "Using the typeof operator in type contexts." +permalink: /zh/docs/handbook/2/typeof-types.html +oneline: "在类型上下文中使用 typeof 操作符" --- -## The `typeof` type operator +## `typeof` 类型操作符 -JavaScript already has a `typeof` operator you can use in an _expression_ context: +在 JavaScript 中,已经有可以应用在 _表达式_ 上下文的 `typeof` 操作符。 ```ts twoslash // Prints "string" console.log(typeof "Hello world"); ``` -TypeScript adds a `typeof` operator you can use in a _type_ context to refer to the _type_ of a variable or property: +TypeScript 新增了可以用在 _类型_ 上下文的 `typeof`,用以推断一个变量或者属性的 _类型_。 ```ts twoslash let s = "hello"; @@ -22,9 +22,9 @@ let n: typeof s; // ^? ``` -This isn't very useful for basic types, but combined with other type operators, you can use `typeof` to conveniently express many patterns. -For an example, let's start by looking at the predefined type `ReturnType`. -It takes a _function type_ and produces its return type: +对于基础类型来说这不是很实用,不过与其它类型操作符结合,您可以用 `typeof` 很方便地表示大量模式。 +例如,让我们先看看这个预定义的 `ReturnType` 类型。 +其接收一个 _函数类型_ 并且产出它的返回值类型: ```ts twoslash type Predicate = (x: unknown) => boolean; @@ -32,7 +32,7 @@ type K = ReturnType; // ^? ``` -If we try to use `ReturnType` on a function name, we see an instructive error: +如果我们想给 `ReturnType` 传一个函数名称,我们会看到一个指示性错误: ```ts twoslash // @errors: 2749 @@ -42,8 +42,8 @@ function f() { type P = ReturnType; ``` -Remember that _values_ and _types_ aren't the same thing. -To refer to the _type_ that the _value `f`_ has, we use `typeof`: +请记住 _值_ 和 _类型_ 不是一回事。 +要推断 `f` 这个 _值_ 的 _类型_,我们需要用到 `typeof`: ```ts twoslash function f() { @@ -53,18 +53,19 @@ type P = ReturnType; // ^? ``` -### Limitations +### 局限性 -TypeScript intentionally limits the sorts of expressions you can use `typeof` on. +TypeScript 有意限制您所能够用 `typeof` 表达式的种类。 -Specifically, it's only legal to use `typeof` on identifiers (i.e. variable names) or their properties. -This helps avoid the confusing trap of writing code you think is executing, but isn't: +特别是,在标识符(即变量名)或其属性上使用 `typeof` 是唯一合法的。 + +这有助于规避您写一些,您认为执行了,但是却没有执行的代码这样的迷惑陷阱。 ```ts twoslash // @errors: 1005 declare const msgbox: () => boolean; // type msgbox = any; // ---cut--- -// Meant to use = ReturnType +// 打算使用 = ReturnType let shouldContinue: typeof msgbox("Are you sure you want to continue?"); ``` From 1a6102df3b8aacfe9a4918d7ab7306634853662a Mon Sep 17 00:00:00 2001 From: zhouLion Date: Sat, 11 Sep 2021 10:10:55 +0800 Subject: [PATCH 11/15] ZH translation: Template literal types --- .../Template Literal Types.md | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md index 3b2090d3..98e2f873 100644 --- a/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md +++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md @@ -1,14 +1,14 @@ --- title: Template Literal Types layout: docs -permalink: /docs/handbook/2/template-literal-types.html -oneline: "Generating mapping types which change properties via template literal strings." +permalink: /zh/docs/handbook/2/template-literal-types.html +oneline: "通过摸板文本字符串生成变更属性的映射类型。" --- -Template literal types build on [string literal types](/docs/handbook/2/everyday-types.html#literal-types), and have the ability to expand into many strings via unions. +模板文本类型基于 [字符串文本类型](/docs/handbook/2/everyday-types.html#literal-types) 创建,并且能够通过联合来扩展多个字符串。 -They have the same syntax as [template literal strings in JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals), but are used in type positions. -When used with concrete literal types, a template literal produces a new string literal type by concatenating the contents. +它们和 [JavaScript 中的模版字面量字符串](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) 的语法是一样的,只是用在了做类型。 +当使用具体的文本类型,模板文本通过连接内容生成新的字符串文本类型。 ```ts twoslash type World = "world"; @@ -17,7 +17,7 @@ type Greeting = `hello ${World}`; // ^? ``` -When a union is used in the interpolated position, the type is the set of every possible string literal that could be represented by each union member: +当在插值位置使用联合时,类型就是是各个联合成员表示的每个可能字符串文字的集合: ```ts twoslash type EmailLocaleIDs = "welcome_email" | "email_heading"; @@ -27,7 +27,7 @@ type AllLocaleIDs = `${EmailLocaleIDs | FooterLocaleIDs}_id`; // ^? ``` -For each interpolated position in the template literal, the unions are cross multiplied: +对于模板文字中的每个插值位置,并集将交叉相乘: ```ts twoslash type EmailLocaleIDs = "welcome_email" | "email_heading"; @@ -40,13 +40,13 @@ type LocaleMessageIDs = `${Lang}_${AllLocaleIDs}`; // ^? ``` -We generally recommend that people use ahead-of-time generation for large string unions, but this is useful in smaller cases. +我们一般建议人们使用提前生成的大型字符串联合,但这在较小的情况下很有用。 -### String Unions in Types +### 类型中的字符串联合 -The power in template literals comes when defining a new string based off an existing string inside a type. +当要基于现有字符串来定义新字符串时,模版文本就大展神威了。 -For example, a common pattern in JavaScript is to extend an object based on the fields that it currently has. We'll provide a type definition for a function which adds support for an `on` function which lets you know when a value has changed: +比如,JavaScript 中的一个常见模式是基于一个对象上现有的字段做扩展。我们要为一个函数提供类型定义,其增加了对 `on` 函数的支持,该函数可以让您知道何时发生了变化: ```ts twoslash // @noErrors @@ -63,19 +63,19 @@ person.on("firstNameChanged", (newValue) => { }); ``` -Notice that `on` listens on the event `"firstNameChanged"`, not just `"firstName"`, template literals provide a way to handle this sort of string manipulation inside the type system: +我们注意到 `on` 监听的是 `firstNameChanged` 事件,而不是 `firstName`,类型系统中模版文本就为处理这种字符串操作铺好了路。 ```ts twoslash type PropEventSource = { on(eventName: `${string & keyof Type}Changed`, callback: (newValue: any) => void): void; }; -/// Create a "watched object" with an 'on' method -/// so that you can watch for changes to properties. +/// 用 'on' 方法创建一个 "watched object" +/// 这样您就可以监听属性的变化了 declare function makeWatchedObject(obj: Type): Type & PropEventSource; ``` -With this, we can build something that errors when given the wrong property: +有了它,我们可以以给定的错误属性,来创建一些错误内容: ```ts twoslash // @errors: 2345 @@ -93,17 +93,17 @@ const person = makeWatchedObject({ person.on("firstNameChanged", () => {}); -// It's typo-resistent +// 可以防止打错字 person.on("firstName", () => {}); person.on("frstNameChanged", () => {}); ``` -### Inference with Template Literals +### 模版文本的推断 -Note how the last examples did not re-use the type of the original value. The callback used an `any`. Template literal types can infer from substitution positions. +请注意,最后的示例中没有重复使用原始值的类型。回调函数使用了 `any`。模版文本类型可以从替换位置进行类型推断。 -We can make our last example generic to infer from parts of the `eventName` string to figure out the associated property. +我们可以将最后示例设置为泛型,从 `eventName` 字符串的部分内容推断,计算出关联的属性。 ```ts twoslash type PropEventSource = { @@ -132,24 +132,25 @@ person.on("ageChanged", newAge => { }) ``` -Here we made `on` into a generic method. +这里我们把 `on` 变成了泛型方法。 -When a user calls with the string `"firstNameChanged'`, TypeScript will try to infer the right type for `Key`. -To do that, it will match `Key` against the content prior to `"Changed"` and infer the string `"firstName"`. -Once TypeScript figures that out, the `on` method can fetch the type of `firstName` on the original object, which is `string` in this case. -Similarly, when called with `"ageChanged"`, TypeScript finds the type for the property `age` which is `number`. +当用户通过字符串 `"firstNameChange"` 调用的时候,TypeScript 会尝试推断 `Key` 的正确类型。 +通过这样,它会去匹配在 `"Changed"` 前面的内容作为 `Key`,并且推断其为字符串 `"firstName"`。 -Inference can be combined in different ways, often to deconstruct strings, and reconstruct them in different ways. +当 TypeScript 计算出这一点,`on` 方法可以得到原始对象上 `firstName` 的类型,在这里它是一个 `string` 类型。 -## Intrinsic String Manipulation Types +同样的,当使用 `"ageChanged"` 进行调用的使用,TypeScript 会发现 `number` 类型的 `age`。 -To help with string manipulation, TypeScript includes a set of types which can be used in string manipulation. These types come built-in to the compiler for performance and can't be found in the `.d.ts` files included with TypeScript. +可以用不同方式进行推断,一般都是分解字符串,然后用不同的方式再组装起来。 +## 内置字符串操作类型 + +为了辅助字符串操作,TypeScript 有一套用在字符串操作的类型集合。出于性能考虑,这些类型内置在编译器,在 TypeScript 附带的 `.d.ts` 中找不到。 ### `Uppercase` -Converts each character in the string to the uppercase version. +将字符串中的每个字符转为大写。 -##### Example +##### 示例 ```ts twoslash type Greeting = "Hello, world" @@ -163,9 +164,9 @@ type MainID = ASCIICacheKey<"my_app"> ### `Lowercase` -Converts each character in the string to the lowercase equivalent. +将字符串中的每个字符转为小写。 -##### Example +##### 示例 ```ts twoslash type Greeting = "Hello, world" @@ -179,8 +180,7 @@ type MainID = ASCIICacheKey<"MY_APP"> ### `Capitalize` -Converts the first character in the string to an uppercase equivalent. - +将字符串中的首个字符转为大写。 ##### Example ```ts twoslash @@ -191,9 +191,9 @@ type Greeting = Capitalize; ### `Uncapitalize` -Converts the first character in the string to a lowercase equivalent. +将字符串中的首个字符转为等效的小写字符 -##### Example +##### 示例 ```ts twoslash type UppercaseGreeting = "HELLO WORLD"; @@ -202,8 +202,8 @@ type UncomfortableGreeting = Uncapitalize; ```
- Technical details on the intrinsic string manipulation types -

The code, as of TypeScript 4.1, for these intrinsic functions uses the JavaScript string runtime functions directly for manipulation and are not locale aware.

+ 内置字符操作类型的细节 +

从 TypeScript 4.1 开始,这些内在函数的代码直接使用 JavaScript 字符串运行时函数进行操作,并且不支持区域本地化设置。

 function applyStringMapping(symbol: Symbol, str: string) {
     switch (intrinsicTypeKinds.get(symbol.escapedName as string)) {

From 1987953f38eda70282579ce1e3a4074665ec5504 Mon Sep 17 00:00:00 2001
From: zhouLion 
Date: Sat, 11 Sep 2021 10:30:37 +0800
Subject: [PATCH 12/15] ZH translations: revise handbook-v2

---
 .../handbook-v2/Type Manipulation/Generics.md | 68 +++++++++----------
 .../Type Manipulation/Indexed Access Types.md | 18 ++---
 .../Type Manipulation/Mapped Types.md         |  5 +-
 .../Template Literal Types.md                 |  1 +
 .../_Creating Types from Types.md             | 16 ++---
 5 files changed, 54 insertions(+), 54 deletions(-)

diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md
index ea7fe3ef..06fb4ae4 100644
--- a/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md	
+++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md	
@@ -1,23 +1,22 @@
 ---
 title: Generics
 layout: docs
-permalink: /docs/handbook/2/generics.html
-oneline: Types which take parameters
+permalink: /zh/docs/handbook/2/generics.html
+oneline: 泛型:带有参数的类型
 ---
 
-A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable.
-Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems.
+软件工程的一个主要部分是构建组件,这些组件不仅具有定义良好且一致的 API,而且还具有可重用性。
+能够处理现在的数据,也可以处理将来的数据的组件,将使您构建大型软件系统时如虎添翼。
 
-In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is _generics_, that is, being able to create a component that can work over a variety of types rather than a single one.
-This allows users to consume these components and use their own types.
+在类似 C# 和 Java 的语言中,创建可复用性组件的一大法宝就是 _泛型_,也就是说,能够创建可以在多种类型而非单一类型上工作的组件。
+这让用户可以按自己的类型去使用组件。
+## 泛型 Hello World
 
-## Hello World of Generics
+首先,让我们通过 identity 函数做一个泛型的 「hello world」:
+identity 函数是一个返回传入内容的函数。
+您可以将其想象为类似 `echo` 命令的方法。
 
-To start off, let's do the "hello world" of generics: the identity function.
-The identity function is a function that will return back whatever is passed in.
-You can think of this in a similar way to the `echo` command.
-
-Without generics, we would either have to give the identity function a specific type:
+没有泛型的情况下,我们可能必须要给这个 identity 函数指定类型:
 
 ```ts twoslash
 function identity(arg: number): number {
@@ -25,7 +24,7 @@ function identity(arg: number): number {
 }
 ```
 
-Or, we could describe the identity function using the `any` type:
+或者,我们可以用 `any` 类型来表示这个 identity 函数:
 
 ```ts twoslash
 function identity(arg: any): any {
@@ -33,11 +32,11 @@ function identity(arg: any): any {
 }
 ```
 
-While using `any` is certainly generic in that it will cause the function to accept any and all types for the type of `arg`, we actually are losing the information about what that type was when the function returns.
-If we passed in a number, the only information we have is that any type could be returned.
+因为使用 `any` 肯定是宽泛的,这导致该函数的 `arg` 可以接收任何和所有的类型,我们实际上就无法得知该函数返回值的类型信息。
+如果我们传入一个数字,我们仅能得到的信息就是,其可能会返回任意类型。
 
-Instead, we need a way of capturing the type of the argument in such a way that we can also use it to denote what is being returned.
-Here, we will use a _type variable_, a special kind of variable that works on types rather than values.
+相反的,我们需要一种途径去得知参数的类型,从而我们可以利用它去表示将返回何种类型。
+在此,我们将使用一个 _类型变量_ ,它是一种工作在类型系统中的变量,而非一般的值。
 
 ```ts twoslash
 function identity(arg: Type): Type {
@@ -45,16 +44,16 @@ function identity(arg: Type): Type {
 }
 ```
 
-We've now added a type variable `Type` to the identity function.
-This `Type` allows us to capture the type the user provides (e.g. `number`), so that we can use that information later.
-Here, we use `Type` again as the return type. On inspection, we can now see the same type is used for the argument and the return type.
-This allows us to traffic that type information in one side of the function and out the other.
+我们刚刚给 identity 函数添加了一个类型变量 `Type`。
+这个 `Type` 允许我们捕获用户传递的参数类型(如 `number`),于是我们待会儿要用到这个信息。
+这里,我们再次使用 `Type` 作为返回类型。通过检查,我们现在可以看到参数和返回类型使用了相同的类型。
+这让我们将类型信息从函数的一侧,传达到其另一侧。
 
-We say that this version of the `identity` function is generic, as it works over a range of types.
-Unlike using `any`, it's also just as precise (ie, it doesn't lose any information) as the first `identity` function that used numbers for the argument and return type.
+我们将这种版本的 `identity` 函数称为泛型,因为它适用于一系列类型。
+与使用 `any` 不一样,这种方式与使用数字作为参数和返回值的那个第一个 `identity` 函数一样精确(如:它不会丢失任何信息)。
 
-Once we've written the generic identity function, we can call it in one of two ways.
-The first way is to pass all of the arguments, including the type argument, to the function:
+当我们写了这个泛型 identity 函数,我们可以通过两种方式去调用它。
+第一种方式是将所有的参数,包括类型的参数,传递给函数:
 
 ```ts twoslash
 function identity(arg: Type): Type {
@@ -65,9 +64,9 @@ let output = identity("myString");
 //       ^?
 ```
 
-Here we explicitly set `Type` to be `string` as one of the arguments to the function call, denoted using the `<>` around the arguments rather than `()`.
+在这里,我们显式地将 `Type` 设置为 `string`,作为函数调用的参数之一,在参数周围使用 `<>` 表示,而不是使用 `()`。
 
-The second way is also perhaps the most common. Here we use _type argument inference_ -- that is, we want the compiler to set the value of `Type` for us automatically based on the type of the argument we pass in:
+第二种方式也许最常见。这里我们使用 _类型参数推导_ -- 也就是,我们想要编译器通过我们所传参数的类型,去自动为我们设置 `Type` 的值:
 
 ```ts twoslash
 function identity(arg: Type): Type {
@@ -78,15 +77,14 @@ let output = identity("myString");
 //       ^?
 ```
 
-Notice that we didn't have to explicitly pass the type in the angle brackets (`<>`); the compiler just looked at the value `"myString"`, and set `Type` to its type.
-While type argument inference can be a helpful tool to keep code shorter and more readable, you may need to explicitly pass in the type arguments as we did in the previous example when the compiler fails to infer the type, as may happen in more complex examples.
-
-## Working with Generic Type Variables
+注意,我们不必显式地传递类型到单方括号(`<>`)里;编译器会顾及 `"myString"` 的值,并设置 `Type` 为其类型。
+虽然类型参数推断是保持代码更短和更可读的有用工具,但当编译器无法推断类型时,您可能需要显式地传递类型参数,就像我们在上一个示例中所做的那样,这可能发生在更复杂的示例中。
+## 使用泛型类型变量
 
-When you begin to use generics, you'll notice that when you create generic functions like `identity`, the compiler will enforce that you use any generically typed parameters in the body of the function correctly.
-That is, that you actually treat these parameters as if they could be any and all types.
+当您开始使用泛型,您将会注意到,当您创建一个像 `identify` 这样的泛型函数时,编译器会强制您在函数体内正确的使用任意的泛型类型参数。
+也就是说,您实际上可以将这些参数视为任何类型。
 
-Let's take our `identity` function from earlier:
+让我们回头看一下 `identity` 函数:
 
 ```ts twoslash
 function identity(arg: Type): Type {
@@ -373,4 +371,4 @@ createInstance(Lion).keeper.nametag;
 createInstance(Bee).keeper.hasMask;
 ```
 
-This pattern is used to power the [mixins](/docs/handbook/mixins.html) design pattern.
+该模式得利于 [mixins](/docs/handbook/mixins.html) 设计模式。
diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md
index b954513e..23d52aed 100644
--- a/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md	
+++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Indexed Access Types.md	
@@ -1,11 +1,11 @@
 ---
 title: Indexed Access Types
 layout: docs
-permalink: /docs/handbook/2/indexed-access-types.html
-oneline: "Using Type['a'] syntax to access a subset of a type."
+permalink: /zh/docs/handbook/2/indexed-access-types.html
+oneline: "通过 `Type['a']` 语法访问一个类型的子集。"
 ---
 
-We can use an _indexed access type_ to look up a specific property on another type:
+我们可以使用 _索引访问类型_ 来查找另一个类型上的特定属性。
 
 ```ts twoslash
 type Person = { age: number; name: string; alive: boolean };
@@ -13,7 +13,7 @@ type Age = Person["age"];
 //   ^?
 ```
 
-The indexing type is itself a type, so we can use unions, `keyof`, or other types entirely:
+索引类型本身就是一个类型,所以我们完全可以使用联合,`typeof`,或者其他类型:
 
 ```ts twoslash
 type Person = { age: number; name: string; alive: boolean };
@@ -29,7 +29,7 @@ type I3 = Person[AliveOrName];
 //   ^?
 ```
 
-You'll even see an error if you try to index a property that doesn't exist:
+试试看索引一个不存在的属性,你会发现报错:
 
 ```ts twoslash
 // @errors: 2339
@@ -38,8 +38,8 @@ type Person = { age: number; name: string; alive: boolean };
 type I1 = Person["alve"];
 ```
 
-Another example of indexing with an arbitrary type is using `number` to get the type of an array's elements.
-We can combine this with `typeof` to conveniently capture the element type of an array literal:
+另一个示例是,使用 `number` 去索引任意类型,可以得到一个数组的元素。
+我们将其与 `typeof` 结合,能很方便地获取数组的元素类型
 
 ```ts twoslash
 const MyArray = [
@@ -57,7 +57,7 @@ type Age2 = Person["age"];
 //   ^?
 ```
 
-You can only use types when indexing, meaning you can't use a `const` to make a variable reference:
+索引时只能使用类型,这意味着不能使用 `const` 进行变量引用:
 
 ```ts twoslash
 // @errors: 2538 2749
@@ -67,7 +67,7 @@ const key = "age";
 type Age = Person[key];
 ```
 
-However, you can use a type alias for a similar style of refactor:
+但是,您可以用类型别名进行类似的重构:
 
 ```ts twoslash
 type Person = { age: number; name: string; alive: boolean };
diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md
index 64bb7b9f..52f7f317 100644
--- a/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md	
+++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Mapped Types.md	
@@ -22,7 +22,7 @@ const conforms: OnlyBoolsAndHorses = {
 };
 ```
 
-映射类型是一种泛型类型,它使用 `PropertyKey` 的联合(通常 [通过 `keyof`](/docs/handbook/2/indexed-access-types.html))来迭代键以创建类型:
+映射类型是一种泛型类型,它使用 `PropertyKey` 的联合(通常 [通过 `keyof`](/zh/docs/handbook/2/indexed-access-types.html))来迭代键以创建类型:
 
 ```ts twoslash
 type OptionsFlags = {
@@ -93,6 +93,7 @@ type MappedTypeWithNewProperties = {
 }
 ```
 
+
 您可以利用 [模版字面量类型](/docs/handbook/2/template-literal-types.html) 等功能,从以前的属性名称创建新的属性名称:
 
 ```ts twoslash
@@ -129,7 +130,7 @@ type KindlessCircle = RemoveKindField;
 
 ### 未来探索
 
-映射类型与此类型操作部分中的其他功能配合得很好,例如,这里有 [使用条件类型的映射类型](/docs/handbook/2/conditional-types.html) 它返回 `true` 或 `false`,这取决于对象是否将属性 `pii` 设置为文字 `true`。
+映射类型与此类型操作部分中的其他功能配合得很好,例如,这里有 [使用条件类型的映射类型](/zh/docs/handbook/2/conditional-types.html) 它返回 `true` 或 `false`,这取决于对象是否将属性 `pii` 设置为文字 `true`。
 
 ```ts twoslash
 type ExtractPII = {
diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md
index 98e2f873..2f695035 100644
--- a/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md	
+++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Template Literal Types.md	
@@ -5,6 +5,7 @@ permalink: /zh/docs/handbook/2/template-literal-types.html
 oneline: "通过摸板文本字符串生成变更属性的映射类型。"
 ---
 
+
 模板文本类型基于 [字符串文本类型](/docs/handbook/2/everyday-types.html#literal-types) 创建,并且能够通过联合来扩展多个字符串。
 
 它们和 [JavaScript 中的模版字面量字符串](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) 的语法是一样的,只是用在了做类型。
diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md b/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md
index 3c4e697a..59a4aa31 100644
--- a/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md	
+++ b/docs/documentation/zh/handbook-v2/Type Manipulation/_Creating Types from Types.md	
@@ -1,7 +1,7 @@
 ---
 title: Creating Types from Types
 layout: docs
-permalink: /docs/handbook/2/types-from-types.html
+permalink: /zh/docs/handbook/2/types-from-types.html
 oneline: "您可通过现有类型创建更多类型的几种方式概览。"
 ---
 
@@ -13,10 +13,10 @@ TypeScript 的类型系统非常强大,因为它允许用其他类型表示类
 通过组合各种类型的运算符,我们可以以简洁、可维护的方式表达复杂的操作和值。
 在本节中,我们将介绍用现有类型或值表示新类型的方法。
 
-- [泛型](/docs/handbook/2/generics.html) - 接收参数的类型
-- [Keyof 类型运算符](/docs/handbook/2/keyof-types.html) - 通过 `keyof` 运算符创建新类型
-- [Typeof 类型运算符](/docs/handbook/2/typeof-types.html) - 通过 `typeof` 运算符创建新类型
-- [按索引访问类型](/docs/handbook/2/indexed-access-types.html) - 通过 `Type['a']` 语法访问一个类型的子集
-- [条件类型](/docs/handbook/2/conditional-types.html) - 在类型系统中像 if 语句那样的类型
-- [映射类型](/docs/handbook/2/mapped-types.html) - 通过已有类型的属性映射创建类型
-- [模版字面量类型](/docs/handbook/2/template-literal-types.html) - 已映射类型,其通过模版字面量字符串,改变其属性
+- [泛型](/zh/docs/handbook/2/generics.html) - 接收参数的类型
+- [Keyof 类型运算符](/zh/docs/handbook/2/keyof-types.html) - 通过 `keyof` 运算符创建新类型
+- [Typeof 类型运算符](/zh/docs/handbook/2/typeof-types.html) - 通过 `typeof` 运算符创建新类型
+- [按索引访问类型](/zh/docs/handbook/2/indexed-access-types.html) - 通过 `Type['a']` 语法访问一个类型的子集
+- [条件类型](/zh/docs/handbook/2/conditional-types.html) - 在类型系统中像 if 语句那样的类型
+- [映射类型](/zh/docs/handbook/2/mapped-types.html) - 通过已有类型的属性映射创建类型
+- [模版字面量类型](/zh/docs/handbook/2/template-literal-types.html) - 已映射类型,其通过模版字面量字符串,改变其属性

From 17460a7377b1b75da767ec1422d2cc8156fa3a53 Mon Sep 17 00:00:00 2001
From: zhouLion 
Date: Sat, 11 Sep 2021 18:58:03 +0800
Subject: [PATCH 13/15] ZH translations: Generics

---
 .../handbook-v2/Type Manipulation/Generics.md | 125 ++++++++++--------
 1 file changed, 68 insertions(+), 57 deletions(-)

diff --git a/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md b/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md
index 06fb4ae4..dda8600f 100644
--- a/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md	
+++ b/docs/documentation/zh/handbook-v2/Type Manipulation/Generics.md	
@@ -2,21 +2,21 @@
 title: Generics
 layout: docs
 permalink: /zh/docs/handbook/2/generics.html
-oneline: 泛型:带有参数的类型
+oneline: 接收参数的类型
 ---
 
 软件工程的一个主要部分是构建组件,这些组件不仅具有定义良好且一致的 API,而且还具有可重用性。
-能够处理现在的数据,也可以处理将来的数据的组件,将使您构建大型软件系统时如虎添翼。
+那些既可以处理现在的数据,也可以处理将来的数据的组件,使您在构建大型软件系统时灵活自如。
 
 在类似 C# 和 Java 的语言中,创建可复用性组件的一大法宝就是 _泛型_,也就是说,能够创建可以在多种类型而非单一类型上工作的组件。
-这让用户可以按自己的类型去使用组件。
+它允许用户可以按照他们自己的类型使用这些组件。
 ## 泛型 Hello World
 
 首先,让我们通过 identity 函数做一个泛型的 「hello world」:
 identity 函数是一个返回传入内容的函数。
 您可以将其想象为类似 `echo` 命令的方法。
 
-没有泛型的情况下,我们可能必须要给这个 identity 函数指定类型:
+没有泛型的情况下,我们可能必须要给这个 `identity` 函数指定类型:
 
 ```ts twoslash
 function identity(arg: number): number {
@@ -92,8 +92,8 @@ function identity(arg: Type): Type {
 }
 ```
 
-What if we want to also log the length of the argument `arg` to the console with each call?
-We might be tempted to write this:
+我们要是想每次调用时,把参数 `arg` 的长度达打印到控制台会怎样?
+我们暂且这样写:
 
 ```ts twoslash
 // @errors: 2339
@@ -103,11 +103,12 @@ function loggingIdentity(arg: Type): Type {
 }
 ```
 
-When we do, the compiler will give us an error that we're using the `.length` member of `arg`, but nowhere have we said that `arg` has this member.
-Remember, we said earlier that these type variables stand in for any and all types, so someone using this function could have passed in a `number` instead, which does not have a `.length` member.
+当我们这样写,编译器将会给我们报错,说我们正在使用 `arg` 的 `.length` 成员,但是我们并没有说过 `arg` 上有该成员。
+请记住,我们之前说过,这些类型变量表示 any 和全部的类型,因此使用此函数的人可能会传入一个没有 `.length` 成员的 `number`。
 
-Let's say that we've actually intended this function to work on arrays of `Type` rather than `Type` directly. Since we're working with arrays, the `.length` member should be available.
-We can describe this just like we would create arrays of other types:
+我们说,我们实际上打算这个函数在 `Type` 数组上工作,而非直接在 `Type`。由于我们使用的是数组,所以才应该有 `.length` 成员。
+
+我们可以像我们将创建其他类型的数组那样描述它:
 
 ```ts twoslash {1}
 function loggingIdentity(arg: Type[]): Type[] {
@@ -116,11 +117,13 @@ function loggingIdentity(arg: Type[]): Type[] {
 }
 ```
 
-You can read the type of `loggingIdentity` as "the generic function `loggingIdentity` takes a type parameter `Type`, and an argument `arg` which is an array of `Type`s, and returns an array of `Type`s."
-If we passed in an array of numbers, we'd get an array of numbers back out, as `Type` would bind to `number`.
-This allows us to use our generic type variable `Type` as part of the types we're working with, rather than the whole type, giving us greater flexibility.
+我们可以把 `loggingIdentity` 的类型理解成 「泛型函数 `loggingIdentity` 接收一个类型参数 `Type`,以及一个参数 `arg`, 该参数是一个以 `Type` 为元素的数组类型,然后返回值是 `Type` 数组」。
+
+我们如果传递一个数字数组,我们将得到一个数字数组返回,因为 `Type` 被绑定为 `number`。
+
+这使得我们可以使用类型变量 `type` 作为我们正在处理的类型中的一部分,而不是整个类型,给了我们更大的灵活性。
 
-We can alternatively write the sample example this way:
+我们也可以这样编写示例:
 
 ```ts twoslash {1}
 function loggingIdentity(arg: Array): Array {
@@ -129,15 +132,15 @@ function loggingIdentity(arg: Array): Array {
 }
 ```
 
-You may already be familiar with this style of type from other languages.
-In the next section, we'll cover how you can create your own generic types like `Array`.
+这样的类型样式您可能在别的语言中似曾相识。
+下一章节,我们将介绍如何创建一个您自己的一个像 `Array` 这样的泛型。
 
-## Generic Types
+## 泛型类型
 
-In previous sections, we created generic identity functions that worked over a range of types.
-In this section, we'll explore the type of the functions themselves and how to create generic interfaces.
+在上一章节中,我们创建了一个泛型函数 `identity`,它适用于一系列类型。
+本章节我们将探索函数自身的类型,以及如何创建泛型接口。
 
-The type of generic functions is just like those of non-generic functions, with the type parameters listed first, similarly to function declarations:
+泛型函数的类型就和那些非泛型函数差不多,首先列出类型参数,就好像声明一个函数:
 
 ```ts twoslash
 function identity(arg: Type): Type {
@@ -147,7 +150,7 @@ function identity(arg: Type): Type {
 let myIdentity: (arg: Type) => Type = identity;
 ```
 
-We could also have used a different name for the generic type parameter in the type, so long as the number of type variables and how the type variables are used line up.
+我们也可能在为泛型的类型参数使用不同的名称,只要类型变量的个数与类型变量实际使用的一致即可。
 
 ```ts twoslash
 function identity(arg: Type): Type {
@@ -157,7 +160,7 @@ function identity(arg: Type): Type {
 let myIdentity: (arg: Input) => Input = identity;
 ```
 
-We can also write the generic type as a call signature of an object literal type:
+我们也可以将泛型类型签名,写成对象字面量那样:
 
 ```ts twoslash
 function identity(arg: Type): Type {
@@ -167,8 +170,8 @@ function identity(arg: Type): Type {
 let myIdentity: { (arg: Type): Type } = identity;
 ```
 
-Which leads us to writing our first generic interface.
-Let's take the object literal from the previous example and move it to an interface:
+这让我们开始编写第一个泛型接口。
+让我们来从上面例子中提取对象字面量,在将其移至一个接口上:
 
 ```ts twoslash
 interface GenericIdentityFn {
@@ -182,9 +185,11 @@ function identity(arg: Type): Type {
 let myIdentity: GenericIdentityFn = identity;
 ```
 
-In a similar example, we may want to move the generic parameter to be a parameter of the whole interface.
-This lets us see what type(s) we're generic over (e.g. `Dictionary` rather than just `Dictionary`).
-This makes the type parameter visible to all the other members of the interface.
+在类似的示例中,我们可能希望将泛型参数移动为整个接口的参数。
+
+这让我们可以看到我们的泛型是什么类型(例如,`Dictionary` 而不仅仅是 `Dictionary`)。
+
+这使类型参数对接口的所有其他成员可见。
 
 ```ts twoslash
 interface GenericIdentityFn {
@@ -198,18 +203,20 @@ function identity(arg: Type): Type {
 let myIdentity: GenericIdentityFn = identity;
 ```
 
-Notice that our example has changed to be something slightly different.
-Instead of describing a generic function, we now have a non-generic function signature that is a part of a generic type.
-When we use `GenericIdentityFn`, we now will also need to specify the corresponding type argument (here: `number`), effectively locking in what the underlying call signature will use.
-Understanding when to put the type parameter directly on the call signature and when to put it on the interface itself will be helpful in describing what aspects of a type are generic.
+请注意,我们对示例稍微做了点改动。
+
+我们现在没有描述泛型函数,而是有一个非泛型函数签名,它是泛型类型的一部分。
 
-In addition to generic interfaces, we can also create generic classes.
-Note that it is not possible to create generic enums and namespaces.
+当我们使用 `GenericIdentityFn`,我们现在还要指定对应类型的参数(这里是:`number`),这有效的限定了底层调用签名将使用的内容。
+理解何时将类型参数直接放在调用签名上,以及何时放在接口它本身上,这将有助于描述类型的那个方面是泛型的。
 
-## Generic Classes
+除了泛型接口,我们还可以创建泛型类。
+请注意,不能创建泛型枚举和命名空间。
 
-A generic class has a similar shape to a generic interface.
-Generic classes have a generic type parameter list in angle brackets (`<>`) following the name of the class.
+## 泛型类
+
+泛型类形似泛型接口。
+泛型类在类名称后面的尖括号 `<>` 内,有一个通用类型参数列表。
 
 ```ts twoslash
 // @strict: false
@@ -224,9 +231,9 @@ myGenericNumber.add = function (x, y) {
   return x + y;
 };
 ```
+这是对 `GenericNumber` 类的一种相当字面的用法,但是您可能已经注意到,并没有限制它只能使用 `number` 类型。
 
-This is a pretty literal use of the `GenericNumber` class, but you may have noticed that nothing is restricting it to only use the `number` type.
-We could have instead used `string` or even more complex objects.
+我们还可以使用 `string` 又或者其他更多复杂的对象。
 
 ```ts twoslash
 // @strict: false
@@ -244,15 +251,16 @@ stringNumeric.add = function (x, y) {
 console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));
 ```
 
-Just as with interface, putting the type parameter on the class itself lets us make sure all of the properties of the class are working with the same type.
+和使用接口一样,给类其本身传类型参数,可以确保类的所有属性都使用相同的类型。
+
+正如我们在 [关于类的章节](/docs/handbook/2/classes.html) 中所述,一个类它的类型分两个方面:静态方面和实例方面。
 
-As we cover in [our section on classes](/docs/handbook/2/classes.html), a class has two sides to its type: the static side and the instance side.
-Generic classes are only generic over their instance side rather than their static side, so when working with classes, static members can not use the class's type parameter.
+泛型类只适用于它们的实例方面而没有使用静态方面,所以当使用类时,静态成员就不能使用类的类型参数。
 
-## Generic Constraints
+## 泛型限制
 
-If you remember from an earlier example, you may sometimes want to write a generic function that works on a set of types where you have _some_ knowledge about what capabilities that set of types will have.
-In our `loggingIdentity` example, we wanted to be able to access the `.length` property of `arg`, but the compiler could not prove that every type had a `.length` property, so it warns us that we can't make this assumption.
+如果您还记得前面的一个示例,那么您有时可能希望编写一个通用函数,该函数可以在一组类型上工作,您对该组类型将具有的功能有一些了解。
+在我们的 `loggingIdentity` 示例中,我们希望能够访问 `arg` 的 `.length` 属性,但编译器无法证明每个类型都有一个 `.length` 属性,因此它警告我们不能这样假设。
 
 ```ts twoslash
 // @errors: 2339
@@ -262,12 +270,13 @@ function loggingIdentity(arg: Type): Type {
 }
 ```
 
-Instead of working with any and all types, we'd like to constrain this function to work with any and all types that *also*  have the `.length` property.
-As long as the type has this member, we'll allow it, but it's required to have at least this member.
-To do so, we must list our requirement as a constraint on what `Type` can be.
+我们不想使用任意和全部类型,而是寄希望于约束这个函数,让其可以使用任何和全部,同时**还**需要有 `.length` 属性。
+只要类型有这个成员,我们就允许使用它,但至少是改成员是必须的。
+
+要做到这一点,我们必须将我们的需求列为 `类型` 的约束条件。
 
-To do so, we'll create an interface that describes our constraint.
-Here, we'll create an interface that has a single `.length` property and then we'll use this interface and the `extends` keyword to denote our constraint:
+为此,我们将创建一个描述约束的接口。
+在这里,我们将创建一个具有单个 `.length` 属性的接口,然后使用此接口和 `extends` 关键字来表示我们的约束:
 
 ```ts twoslash
 interface Lengthwise {
@@ -296,7 +305,7 @@ function loggingIdentity(arg: Type): Type {
 loggingIdentity(3);
 ```
 
-Instead, we need to pass in values whose type has all the required properties:
+相反,我们需要传入其类型具有所有必需属性的值:
 
 ```ts twoslash
 interface Lengthwise {
@@ -311,11 +320,13 @@ function loggingIdentity(arg: Type): Type {
 loggingIdentity({ length: 10, value: 3 });
 ```
 
-## Using Type Parameters in Generic Constraints
+## 在泛型约束中使用类型参数
+
+可以声明受其他类型参数约束的类型参数。
+
+例如,这里我们希望从给定名称的对象中获取属性。
 
-You can declare a type parameter that is constrained by another type parameter.
-For example, here we'd like to get a property from an object given its name.
-We'd like to ensure that we're not accidentally grabbing a property that does not exist on the `obj`, so we'll place a constraint between the two types:
+我们希望确保不会意外获取 `obj` 上不存在的属性,因此我们将在这两种类型之间放置一个约束:
 
 ```ts twoslash
 // @errors: 2345
@@ -329,9 +340,9 @@ getProperty(x, "a");
 getProperty(x, "m");
 ```
 
-## Using Class Types in Generics
+## 在泛型中使用 class 类型
 
-When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions. For example,
+当在 TypeScript 中使用泛型创建一个工厂函数,必须用 class 的构造函数引用到 class 的类型。比如,
 
 ```ts twoslash
 function create(c: { new (): Type }): Type {
@@ -339,7 +350,7 @@ function create(c: { new (): Type }): Type {
 }
 ```
 
-A more advanced example uses the prototype property to infer and constrain relationships between the constructor function and the instance side of class types.
+更高级的示例,使用 prototype 属性来推断和约束构造函数和类类型的实例端之间的关系。
 
 ```ts twoslash
 // @strict: false

From 27595fb7a546a2c571361c486ff250b403600568 Mon Sep 17 00:00:00 2001
From: zhouLion 
Date: Sun, 12 Sep 2021 09:59:35 +0800
Subject: [PATCH 14/15] zh translation: remove untranslated articles

---
 .../zh/declaration-files/By Example.md        |   251 -
 .../zh/declaration-files/Consumption.md       |    44 -
 .../zh/declaration-files/Deep Dive.md         |   232 -
 .../zh/declaration-files/Do's and Don'ts.md   |   241 -
 .../zh/declaration-files/Introduction.md      |    53 -
 .../declaration-files/Library Structures.md   |   326 -
 .../zh/declaration-files/Publishing.md        |   182 -
 .../zh/declaration-files/Templates.md         |    15 -
 .../templates/global-modifying-module.d.ts.md |    72 -
 .../templates/global-plugin.d.ts.md           |   307 -
 .../templates/global.d.ts.md                  |   144 -
 .../templates/module-class.d.ts.md            |    83 -
 .../templates/module-function.d.ts.md         |    85 -
 .../templates/module-plugin.d.ts.md           |    67 -
 .../templates/module.d.ts.md                  |   311 -
 .../TS for Functional Programmers.md          |   597 -
 .../zh/get-started/TS for JS Programmers.md   |   289 -
 .../zh/get-started/TS for OOPers.md           |   194 -
 .../get-started/TS for the New Programmer.md  |   194 -
 .../zh/handbook-v1/Basic Types.md             |   417 -
 docs/documentation/zh/handbook-v1/Classes.md  |   611 -
 .../documentation/zh/handbook-v1/Functions.md |   546 -
 docs/documentation/zh/handbook-v1/Generics.md |   376 -
 .../zh/handbook-v1/Interfaces.md              |   717 --
 .../zh/handbook-v1/Literal Types.md           |   120 -
 .../handbook-v1/Unions and Intersections.md   |   412 -
 docs/documentation/zh/handbook-v2/Basics.md   |   440 -
 docs/documentation/zh/handbook-v2/Classes.md  |  1414 ---
 .../zh/handbook-v2/Everyday Types.md          |   714 --
 docs/documentation/zh/handbook-v2/Modules.md  |   385 -
 .../zh/handbook-v2/More on Functions.md       |   867 --
 .../documentation/zh/handbook-v2/Narrowing.md |   769 --
 .../zh/handbook-v2/Object Types.md            |   948 --
 .../zh/handbook-v2/Type Declarations.md       |   100 -
 .../handbook-v2/Type Manipulation/Generics.md |    55 +-
 .../_Creating Types from Types.md             |     4 +-
 .../zh/handbook-v2/Understanding Errors.md    |    71 -
 .../javascript/Creating DTS files From JS.md  |     2 +-
 .../zh/javascript/Intro to JS with TS.md      |    12 +-
 .../Compiler Options in MSBuild.md            |   600 -
 .../zh/project-config/Compiler Options.md     |  1147 --
 .../zh/project-config/Configuring Watch.md    |    74 -
 .../Integrating with Build Tools.md           |   270 -
 .../zh/project-config/Project References.md   |   222 -
 .../zh/reference/Advanced Types.md            |  1201 --
 .../zh/reference/Declaration Merging.md       |   330 -
 docs/documentation/zh/reference/Decorators.md |   607 -
 docs/documentation/zh/reference/Enums.md      |   419 -
 .../zh/reference/Iterators and Generators.md  |   100 -
 docs/documentation/zh/reference/JSX.md        |   444 -
 docs/documentation/zh/reference/Mixins.md     |   274 -
 .../zh/reference/Module Resolution.md         |   459 -
 docs/documentation/zh/reference/Modules.md    |   919 --
 .../zh/reference/Namespaces and Modules.md    |   128 -
 docs/documentation/zh/reference/Namespaces.md |   281 -
 docs/documentation/zh/reference/Symbols.md    |   107 -
 .../zh/reference/Triple-Slash Directives.md   |   144 -
 .../zh/reference/Type Compatibility.md        |   404 -
 .../zh/reference/Type Inference.md            |   163 -
 .../zh/reference/Utility Types.md             |   505 -
 .../zh/reference/Variable Declarations.md     |   706 --
 .../zh/release-notes/Overview.md              | 10423 ----------------
 .../zh/release-notes/TypeScript 1.1.md        |    28 -
 .../zh/release-notes/TypeScript 1.3.md        |    55 -
 .../zh/release-notes/TypeScript 1.4.md        |   261 -
 .../zh/release-notes/TypeScript 1.5.md        |   393 -
 .../zh/release-notes/TypeScript 1.6.md        |   462 -
 .../zh/release-notes/TypeScript 1.7.md        |   214 -
 .../zh/release-notes/TypeScript 1.8.md        |   600 -
 .../zh/release-notes/TypeScript 2.0.md        |   944 --
 .../zh/release-notes/TypeScript 2.1.md        |   522 -
 .../zh/release-notes/TypeScript 2.2.md        |   212 -
 .../zh/release-notes/TypeScript 2.3.md        |   195 -
 .../zh/release-notes/TypeScript 2.4.md        |   170 -
 .../zh/release-notes/TypeScript 2.5.md        |    47 -
 .../zh/release-notes/TypeScript 2.6.md        |   273 -
 .../zh/release-notes/TypeScript 2.7.md        |   393 -
 .../zh/release-notes/TypeScript 2.8.md        |   427 -
 .../zh/release-notes/TypeScript 2.9.md        |   336 -
 .../zh/release-notes/TypeScript 3.0.md        |   356 -
 .../zh/release-notes/TypeScript 3.1.md        |    76 -
 .../zh/release-notes/TypeScript 3.2.md        |   224 -
 .../zh/release-notes/TypeScript 3.3.md        |   118 -
 .../zh/release-notes/TypeScript 3.4.md        |   437 -
 .../zh/release-notes/TypeScript 3.5.md        |   230 -
 .../zh/release-notes/TypeScript 3.6.md        |   342 -
 .../zh/release-notes/TypeScript 3.7.md        |   849 --
 .../zh/release-notes/TypeScript 3.8.md        |   454 -
 .../zh/release-notes/TypeScript 3.9.md        |   543 -
 .../zh/release-notes/TypeScript 4.0.md        |   738 --
 .../zh/release-notes/TypeScript 4.1.md        |   654 -
 .../zh/release-notes/TypeScript 4.2.md        |   681 -
 .../zh/release-notes/TypeScript 4.3.md        |   865 --
 .../zh/release-notes/TypeScript 4.4.md        |   678 -
 .../zh/tutorials/ASP.NET Core.md              |   215 -
 .../zh/tutorials/Babel with TypeScript.md     |    49 -
 .../zh/tutorials/DOM Manipulation.md          |   201 -
 docs/documentation/zh/tutorials/Gulp.md       |   467 -
 .../zh/tutorials/Migrating from JavaScript.md |   442 -
 docs/documentation/zh/tutorials/React.md      |    26 -
 .../TypeScript Tooling in 5 minutes.md        |   187 -
 101 files changed, 35 insertions(+), 46923 deletions(-)
 delete mode 100644 docs/documentation/zh/declaration-files/By Example.md
 delete mode 100644 docs/documentation/zh/declaration-files/Consumption.md
 delete mode 100644 docs/documentation/zh/declaration-files/Deep Dive.md
 delete mode 100644 docs/documentation/zh/declaration-files/Do's and Don'ts.md
 delete mode 100644 docs/documentation/zh/declaration-files/Introduction.md
 delete mode 100644 docs/documentation/zh/declaration-files/Library Structures.md
 delete mode 100644 docs/documentation/zh/declaration-files/Publishing.md
 delete mode 100644 docs/documentation/zh/declaration-files/Templates.md
 delete mode 100644 docs/documentation/zh/declaration-files/templates/global-modifying-module.d.ts.md
 delete mode 100644 docs/documentation/zh/declaration-files/templates/global-plugin.d.ts.md
 delete mode 100644 docs/documentation/zh/declaration-files/templates/global.d.ts.md
 delete mode 100644 docs/documentation/zh/declaration-files/templates/module-class.d.ts.md
 delete mode 100644 docs/documentation/zh/declaration-files/templates/module-function.d.ts.md
 delete mode 100644 docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md
 delete mode 100644 docs/documentation/zh/declaration-files/templates/module.d.ts.md
 delete mode 100644 docs/documentation/zh/get-started/TS for Functional Programmers.md
 delete mode 100644 docs/documentation/zh/get-started/TS for JS Programmers.md
 delete mode 100644 docs/documentation/zh/get-started/TS for OOPers.md
 delete mode 100644 docs/documentation/zh/get-started/TS for the New Programmer.md
 delete mode 100644 docs/documentation/zh/handbook-v1/Basic Types.md
 delete mode 100644 docs/documentation/zh/handbook-v1/Classes.md
 delete mode 100644 docs/documentation/zh/handbook-v1/Functions.md
 delete mode 100644 docs/documentation/zh/handbook-v1/Generics.md
 delete mode 100644 docs/documentation/zh/handbook-v1/Interfaces.md
 delete mode 100644 docs/documentation/zh/handbook-v1/Literal Types.md
 delete mode 100644 docs/documentation/zh/handbook-v1/Unions and Intersections.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Basics.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Classes.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Everyday Types.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Modules.md
 delete mode 100644 docs/documentation/zh/handbook-v2/More on Functions.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Narrowing.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Object Types.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Type Declarations.md
 delete mode 100644 docs/documentation/zh/handbook-v2/Understanding Errors.md
 delete mode 100644 docs/documentation/zh/project-config/Compiler Options in MSBuild.md
 delete mode 100644 docs/documentation/zh/project-config/Compiler Options.md
 delete mode 100644 docs/documentation/zh/project-config/Configuring Watch.md
 delete mode 100644 docs/documentation/zh/project-config/Integrating with Build Tools.md
 delete mode 100644 docs/documentation/zh/project-config/Project References.md
 delete mode 100644 docs/documentation/zh/reference/Advanced Types.md
 delete mode 100644 docs/documentation/zh/reference/Declaration Merging.md
 delete mode 100644 docs/documentation/zh/reference/Decorators.md
 delete mode 100644 docs/documentation/zh/reference/Enums.md
 delete mode 100644 docs/documentation/zh/reference/Iterators and Generators.md
 delete mode 100644 docs/documentation/zh/reference/JSX.md
 delete mode 100644 docs/documentation/zh/reference/Mixins.md
 delete mode 100644 docs/documentation/zh/reference/Module Resolution.md
 delete mode 100644 docs/documentation/zh/reference/Modules.md
 delete mode 100644 docs/documentation/zh/reference/Namespaces and Modules.md
 delete mode 100644 docs/documentation/zh/reference/Namespaces.md
 delete mode 100644 docs/documentation/zh/reference/Symbols.md
 delete mode 100644 docs/documentation/zh/reference/Triple-Slash Directives.md
 delete mode 100644 docs/documentation/zh/reference/Type Compatibility.md
 delete mode 100644 docs/documentation/zh/reference/Type Inference.md
 delete mode 100644 docs/documentation/zh/reference/Utility Types.md
 delete mode 100644 docs/documentation/zh/reference/Variable Declarations.md
 delete mode 100644 docs/documentation/zh/release-notes/Overview.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 1.1.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 1.3.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 1.4.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 1.5.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 1.6.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 1.7.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 1.8.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.0.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.1.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.2.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.3.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.4.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.5.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.6.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.7.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.8.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 2.9.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.0.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.1.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.2.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.3.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.4.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.5.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.6.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.7.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.8.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 3.9.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 4.0.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 4.1.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 4.2.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 4.3.md
 delete mode 100644 docs/documentation/zh/release-notes/TypeScript 4.4.md
 delete mode 100644 docs/documentation/zh/tutorials/ASP.NET Core.md
 delete mode 100644 docs/documentation/zh/tutorials/Babel with TypeScript.md
 delete mode 100755 docs/documentation/zh/tutorials/DOM Manipulation.md
 delete mode 100644 docs/documentation/zh/tutorials/Gulp.md
 delete mode 100644 docs/documentation/zh/tutorials/Migrating from JavaScript.md
 delete mode 100644 docs/documentation/zh/tutorials/React.md
 delete mode 100644 docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md

diff --git a/docs/documentation/zh/declaration-files/By Example.md b/docs/documentation/zh/declaration-files/By Example.md
deleted file mode 100644
index 6717d697..00000000
--- a/docs/documentation/zh/declaration-files/By Example.md	
+++ /dev/null
@@ -1,251 +0,0 @@
----
-title: Declaration Reference
-layout: docs
-permalink: /docs/handbook/declaration-files/by-example.html
-oneline: "How to create a d.ts file for a module"
----
-
-The purpose of this guide is to teach you how to write a high-quality definition file.
-This guide is structured by showing documentation for some API, along with sample usage of that API,
-and explaining how to write the corresponding declaration.
-
-These examples are ordered in approximately increasing order of complexity.
-
-## Objects with Properties
-
-_Documentation_
-
-> The global variable `myLib` has a function `makeGreeting` for creating greetings,
-> and a property `numberOfGreetings` indicating the number of greetings made so far.
-
-_Code_
-
-```ts
-let result = myLib.makeGreeting("hello, world");
-console.log("The computed greeting is:" + result);
-
-let count = myLib.numberOfGreetings;
-```
-
-_Declaration_
-
-Use `declare namespace` to describe types or values accessed by dotted notation.
-
-```ts
-declare namespace myLib {
-  function makeGreeting(s: string): string;
-  let numberOfGreetings: number;
-}
-```
-
-## Overloaded Functions
-
-_Documentation_
-
-The `getWidget` function accepts a number and returns a Widget, or accepts a string and returns a Widget array.
-
-_Code_
-
-```ts
-let x: Widget = getWidget(43);
-
-let arr: Widget[] = getWidget("all of them");
-```
-
-_Declaration_
-
-```ts
-declare function getWidget(n: number): Widget;
-declare function getWidget(s: string): Widget[];
-```
-
-## Reusable Types (Interfaces)
-
-_Documentation_
-
-> When specifying a greeting, you must pass a `GreetingSettings` object.
-> This object has the following properties:
->
-> 1 - greeting: Mandatory string
->
-> 2 - duration: Optional length of time (in milliseconds)
->
-> 3 - color: Optional string, e.g. '#ff00ff'
-
-_Code_
-
-```ts
-greet({
-  greeting: "hello world",
-  duration: 4000
-});
-```
-
-_Declaration_
-
-Use an `interface` to define a type with properties.
-
-```ts
-interface GreetingSettings {
-  greeting: string;
-  duration?: number;
-  color?: string;
-}
-
-declare function greet(setting: GreetingSettings): void;
-```
-
-## Reusable Types (Type Aliases)
-
-_Documentation_
-
-> Anywhere a greeting is expected, you can provide a `string`, a function returning a `string`, or a `Greeter` instance.
-
-_Code_
-
-```ts
-function getGreeting() {
-  return "howdy";
-}
-class MyGreeter extends Greeter {}
-
-greet("hello");
-greet(getGreeting);
-greet(new MyGreeter());
-```
-
-_Declaration_
-
-You can use a type alias to make a shorthand for a type:
-
-```ts
-type GreetingLike = string | (() => string) | MyGreeter;
-
-declare function greet(g: GreetingLike): void;
-```
-
-## Organizing Types
-
-_Documentation_
-
-> The `greeter` object can log to a file or display an alert.
-> You can provide LogOptions to `.log(...)` and alert options to `.alert(...)`
-
-_Code_
-
-```ts
-const g = new Greeter("Hello");
-g.log({ verbose: true });
-g.alert({ modal: false, title: "Current Greeting" });
-```
-
-_Declaration_
-
-Use namespaces to organize types.
-
-```ts
-declare namespace GreetingLib {
-  interface LogOptions {
-    verbose?: boolean;
-  }
-  interface AlertOptions {
-    modal: boolean;
-    title?: string;
-    color?: string;
-  }
-}
-```
-
-You can also create nested namespaces in one declaration:
-
-```ts
-declare namespace GreetingLib.Options {
-  // Refer to via GreetingLib.Options.Log
-  interface Log {
-    verbose?: boolean;
-  }
-  interface Alert {
-    modal: boolean;
-    title?: string;
-    color?: string;
-  }
-}
-```
-
-## Classes
-
-_Documentation_
-
-> You can create a greeter by instantiating the `Greeter` object, or create a customized greeter by extending from it.
-
-_Code_
-
-```ts
-const myGreeter = new Greeter("hello, world");
-myGreeter.greeting = "howdy";
-myGreeter.showGreeting();
-
-class SpecialGreeter extends Greeter {
-  constructor() {
-    super("Very special greetings");
-  }
-}
-```
-
-_Declaration_
-
-Use `declare class` to describe a class or class-like object.
-Classes can have properties and methods as well as a constructor.
-
-```ts
-declare class Greeter {
-  constructor(greeting: string);
-
-  greeting: string;
-  showGreeting(): void;
-}
-```
-
-## Global Variables
-
-_Documentation_
-
-> The global variable `foo` contains the number of widgets present.
-
-_Code_
-
-```ts
-console.log("Half the number of widgets is " + foo / 2);
-```
-
-_Declaration_
-
-Use `declare var` to declare variables.
-If the variable is read-only, you can use `declare const`.
-You can also use `declare let` if the variable is block-scoped.
-
-```ts
-/** The number of widgets present */
-declare var foo: number;
-```
-
-## Global Functions
-
-_Documentation_
-
-> You can call the function `greet` with a string to show a greeting to the user.
-
-_Code_
-
-```ts
-greet("hello, world");
-```
-
-_Declaration_
-
-Use `declare function` to declare functions.
-
-```ts
-declare function greet(greeting: string): void;
-```
-
diff --git a/docs/documentation/zh/declaration-files/Consumption.md b/docs/documentation/zh/declaration-files/Consumption.md
deleted file mode 100644
index a68c03b2..00000000
--- a/docs/documentation/zh/declaration-files/Consumption.md
+++ /dev/null
@@ -1,44 +0,0 @@
----
-title: Consumption
-layout: docs
-permalink: /docs/handbook/declaration-files/consumption.html
-oneline: "How to download d.ts files for your project"
----
-
-## Downloading
-
-Getting type declarations requires no tools apart from npm.
-
-As an example, getting the declarations for a library like lodash takes nothing more than the following command
-
-```cmd
-npm install --save-dev @types/lodash
-```
-
-It is worth noting that if the npm package already includes its declaration file as described in [Publishing](/docs/handbook/declaration-files/publishing.html), downloading the corresponding `@types` package is not needed.
-
-## Consuming
-
-From there you’ll be able to use lodash in your TypeScript code with no fuss.
-This works for both modules and global code.
-
-For example, once you’ve `npm install`-ed your type declarations, you can use imports and write
-
-```ts
-import * as _ from "lodash";
-_.padStart("Hello TypeScript!", 20, " ");
-```
-
-or if you’re not using modules, you can just use the global variable `_`.
-
-```ts
-_.padStart("Hello TypeScript!", 20, " ");
-```
-
-## Searching
-
-For the most part, type declaration packages should always have the same name as the package name on `npm`, but prefixed with `@types/`,
-but if you need, you can check out [this Type Search](https://aka.ms/types) to find the package for your favorite library.
-
-> Note: if the declaration file you are searching for is not present, you can always contribute one back and help out the next developer looking for it.
-> Please see the DefinitelyTyped [contribution guidelines page](http://definitelytyped.org/guides/contributing.html) for details.
diff --git a/docs/documentation/zh/declaration-files/Deep Dive.md b/docs/documentation/zh/declaration-files/Deep Dive.md
deleted file mode 100644
index 89950e96..00000000
--- a/docs/documentation/zh/declaration-files/Deep Dive.md	
+++ /dev/null
@@ -1,232 +0,0 @@
----
-title: Deep Dive
-layout: docs
-permalink: /docs/handbook/declaration-files/deep-dive.html
-oneline: "How do d.ts files work, a deep dive"
----
-
-## Declaration File Theory: A Deep Dive
-
-Structuring modules to give the exact API shape you want can be tricky.
-For example, we might want a module that can be invoked with or without `new` to produce different types,
-has a variety of named types exposed in a hierarchy,
-and has some properties on the module object as well.
-
-By reading this guide, you'll have the tools to write complex declaration files that expose a friendly API surface.
-This guide focuses on module (or UMD) libraries because the options here are more varied.
-
-## Key Concepts
-
-You can fully understand how to make any shape of declaration
-by understanding some key concepts of how TypeScript works.
-
-### Types
-
-If you're reading this guide, you probably already roughly know what a type in TypeScript is.
-To be more explicit, though, a _type_ is introduced with:
-
-- A type alias declaration (`type sn = number | string;`)
-- An interface declaration (`interface I { x: number[]; }`)
-- A class declaration (`class C { }`)
-- An enum declaration (`enum E { A, B, C }`)
-- An `import` declaration which refers to a type
-
-Each of these declaration forms creates a new type name.
-
-### Values
-
-As with types, you probably already understand what a value is.
-Values are runtime names that we can reference in expressions.
-For example `let x = 5;` creates a value called `x`.
-
-Again, being explicit, the following things create values:
-
-- `let`, `const`, and `var` declarations
-- A `namespace` or `module` declaration which contains a value
-- An `enum` declaration
-- A `class` declaration
-- An `import` declaration which refers to a value
-- A `function` declaration
-
-### Namespaces
-
-Types can exist in _namespaces_.
-For example, if we have the declaration `let x: A.B.C`,
-we say that the type `C` comes from the `A.B` namespace.
-
-This distinction is subtle and important -- here, `A.B` is not necessarily a type or a value.
-
-## Simple Combinations: One name, multiple meanings
-
-Given a name `A`, we might find up to three different meanings for `A`: a type, a value or a namespace.
-How the name is interpreted depends on the context in which it is used.
-For example, in the declaration `let m: A.A = A;`,
-`A` is used first as a namespace, then as a type name, then as a value.
-These meanings might end up referring to entirely different declarations!
-
-This may seem confusing, but it's actually very convenient as long as we don't excessively overload things.
-Let's look at some useful aspects of this combining behavior.
-
-### Built-in Combinations
-
-Astute readers will notice that, for example, `class` appeared in both the _type_ and _value_ lists.
-The declaration `class C { }` creates two things:
-a _type_ `C` which refers to the instance shape of the class,
-and a _value_ `C` which refers to the constructor function of the class.
-Enum declarations behave similarly.
-
-### User Combinations
-
-Let's say we wrote a module file `foo.d.ts`:
-
-```ts
-export var SomeVar: { a: SomeType };
-export interface SomeType {
-  count: number;
-}
-```
-
-Then consumed it:
-
-```ts
-import * as foo from "./foo";
-let x: foo.SomeType = foo.SomeVar.a;
-console.log(x.count);
-```
-
-This works well enough, but we might imagine that `SomeType` and `SomeVar` were very closely related
-such that you'd like them to have the same name.
-We can use combining to present these two different objects (the value and the type) under the same name `Bar`:
-
-```ts
-export var Bar: { a: Bar };
-export interface Bar {
-  count: number;
-}
-```
-
-This presents a very good opportunity for destructuring in the consuming code:
-
-```ts
-import { Bar } from "./foo";
-let x: Bar = Bar.a;
-console.log(x.count);
-```
-
-Again, we've used `Bar` as both a type and a value here.
-Note that we didn't have to declare the `Bar` value as being of the `Bar` type -- they're independent.
-
-## Advanced Combinations
-
-Some kinds of declarations can be combined across multiple declarations.
-For example, `class C { }` and `interface C { }` can co-exist and both contribute properties to the `C` types.
-
-This is legal as long as it does not create a conflict.
-A general rule of thumb is that values always conflict with other values of the same name unless they are declared as `namespace`s,
-types will conflict if they are declared with a type alias declaration (`type s = string`),
-and namespaces never conflict.
-
-Let's see how this can be used.
-
-### Adding using an `interface`
-
-We can add additional members to an `interface` with another `interface` declaration:
-
-```ts
-interface Foo {
-  x: number;
-}
-// ... elsewhere ...
-interface Foo {
-  y: number;
-}
-let a: Foo = ...;
-console.log(a.x + a.y); // OK
-```
-
-This also works with classes:
-
-```ts
-class Foo {
-  x: number;
-}
-// ... elsewhere ...
-interface Foo {
-  y: number;
-}
-let a: Foo = ...;
-console.log(a.x + a.y); // OK
-```
-
-Note that we cannot add to type aliases (`type s = string;`) using an interface.
-
-### Adding using a `namespace`
-
-A `namespace` declaration can be used to add new types, values, and namespaces in any way which does not create a conflict.
-
-For example, we can add a static member to a class:
-
-```ts
-class C {}
-// ... elsewhere ...
-namespace C {
-  export let x: number;
-}
-let y = C.x; // OK
-```
-
-Note that in this example, we added a value to the _static_ side of `C` (its constructor function).
-This is because we added a _value_, and the container for all values is another value
-(types are contained by namespaces, and namespaces are contained by other namespaces).
-
-We could also add a namespaced type to a class:
-
-```ts
-class C {}
-// ... elsewhere ...
-namespace C {
-  export interface D {}
-}
-let y: C.D; // OK
-```
-
-In this example, there wasn't a namespace `C` until we wrote the `namespace` declaration for it.
-The meaning `C` as a namespace doesn't conflict with the value or type meanings of `C` created by the class.
-
-Finally, we could perform many different merges using `namespace` declarations.
-This isn't a particularly realistic example, but shows all sorts of interesting behavior:
-
-```ts
-namespace X {
-  export interface Y {}
-  export class Z {}
-}
-
-// ... elsewhere ...
-namespace X {
-  export var Y: number;
-  export namespace Z {
-    export class C {}
-  }
-}
-type X = string;
-```
-
-In this example, the first block creates the following name meanings:
-
-- A value `X` (because the `namespace` declaration contains a value, `Z`)
-- A namespace `X` (because the `namespace` declaration contains a type, `Y`)
-- A type `Y` in the `X` namespace
-- A type `Z` in the `X` namespace (the instance shape of the class)
-- A value `Z` that is a property of the `X` value (the constructor function of the class)
-
-The second block creates the following name meanings:
-
-- A value `Y` (of type `number`) that is a property of the `X` value
-- A namespace `Z`
-- A value `Z` that is a property of the `X` value
-- A type `C` in the `X.Z` namespace
-- A value `C` that is a property of the `X.Z` value
-- A type `X`
-
-
diff --git a/docs/documentation/zh/declaration-files/Do's and Don'ts.md b/docs/documentation/zh/declaration-files/Do's and Don'ts.md
deleted file mode 100644
index 34ddcbd8..00000000
--- a/docs/documentation/zh/declaration-files/Do's and Don'ts.md	
+++ /dev/null
@@ -1,241 +0,0 @@
----
-title: Do's and Don'ts
-layout: docs
-permalink: /docs/handbook/declaration-files/do-s-and-don-ts.html
-oneline: "Recommendations for writing d.ts files"
----
-
-## General Types
-
-## `Number`, `String`, `Boolean`, `Symbol` and `Object`
-
-❌ **Don't** ever use the types `Number`, `String`, `Boolean`, `Symbol`, or `Object`
-These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code.
-
-```ts
-/* WRONG */
-function reverse(s: String): String;
-```
-
-✅ **Do** use the types `number`, `string`, `boolean`, and `symbol`.
-
-```ts
-/* OK */
-function reverse(s: string): string;
-```
-
-Instead of `Object`, use the non-primitive `object` type ([added in TypeScript 2.2](../release-notes/typescript-2-2.html#object-type)).
-
-## Generics
-
-❌ **Don't** ever have a generic type which doesn't use its type parameter.
-See more details in [TypeScript FAQ page](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-type-inference-work-on-this-interface-interface-foot--).
-
-## any
-
-❌ **Don't** use `any` as a type unless you are in the process of migrating a JavaScript project to TypeScript.  The compiler _effectively_ treats `any` as "please turn off type checking for this thing".  It is similar to putting an `@ts-ignore` comment around every usage of the variable.  This can be very helpful when you are first migrating a JavaScript project to TypeScript as you can set the type for stuff you haven't migrated yet as `any`, but in a full TypeScript project you are disabling type checking for any parts of your program that use it.
-
-In cases where you don't know what type you want to accept, or when you want to accept anything because you will be blindly passing it through without interacting with it, you can use [`unknown`](/play/#example/unknown-and-never).
-
-
-
-## Callback Types
-
-## Return Types of Callbacks
-
-
-
-❌ **Don't** use the return type `any` for callbacks whose value will be ignored:
-
-```ts
-/* WRONG */
-function fn(x: () => any) {
-  x();
-}
-```
-
-✅ **Do** use the return type `void` for callbacks whose value will be ignored:
-
-```ts
-/* OK */
-function fn(x: () => void) {
-  x();
-}
-```
-
-❔ **Why:** Using `void` is safer because it prevents you from accidentally using the return value of `x` in an unchecked way:
-
-```ts
-function fn(x: () => void) {
-  var k = x(); // oops! meant to do something else
-  k.doSomething(); // error, but would be OK if the return type had been 'any'
-}
-```
-
-## Optional Parameters in Callbacks
-
-❌ **Don't** use optional parameters in callbacks unless you really mean it:
-
-```ts
-/* WRONG */
-interface Fetcher {
-  getObject(done: (data: any, elapsedTime?: number) => void): void;
-}
-```
-
-This has a very specific meaning: the `done` callback might be invoked with 1 argument or might be invoked with 2 arguments.
-The author probably intended to say that the callback might not care about the `elapsedTime` parameter,
-but there's no need to make the parameter optional to accomplish this --
-it's always legal to provide a callback that accepts fewer arguments.
-
-✅ **Do** write callback parameters as non-optional:
-
-```ts
-/* OK */
-interface Fetcher {
-  getObject(done: (data: any, elapsedTime: number) => void): void;
-}
-```
-
-## Overloads and Callbacks
-
-❌ **Don't** write separate overloads that differ only on callback arity:
-
-```ts
-/* WRONG */
-declare function beforeAll(action: () => void, timeout?: number): void;
-declare function beforeAll(
-  action: (done: DoneFn) => void,
-  timeout?: number
-): void;
-```
-
-✅ **Do** write a single overload using the maximum arity:
-
-```ts
-/* OK */
-declare function beforeAll(
-  action: (done: DoneFn) => void,
-  timeout?: number
-): void;
-```
-
-❔ **Why:** It's always legal for a callback to disregard a parameter, so there's no need for the shorter overload.
-Providing a shorter callback first allows incorrectly-typed functions to be passed in because they match the first overload.
-
-## Function Overloads
-
-## Ordering
-
-❌ **Don't** put more general overloads before more specific overloads:
-
-```ts
-/* WRONG */
-declare function fn(x: any): any;
-declare function fn(x: HTMLElement): number;
-declare function fn(x: HTMLDivElement): string;
-
-var myElem: HTMLDivElement;
-var x = fn(myElem); // x: any, wat?
-```
-
-✅ **Do** sort overloads by putting the more general signatures after more specific signatures:
-
-```ts
-/* OK */
-declare function fn(x: HTMLDivElement): string;
-declare function fn(x: HTMLElement): number;
-declare function fn(x: any): any;
-
-var myElem: HTMLDivElement;
-var x = fn(myElem); // x: string, :)
-```
-
-❔ **Why:** TypeScript chooses the _first matching overload_ when resolving function calls.
-When an earlier overload is "more general" than a later one, the later one is effectively hidden and cannot be called.
-
-## Use Optional Parameters
-
-❌ **Don't** write several overloads that differ only in trailing parameters:
-
-```ts
-/* WRONG */
-interface Example {
-  diff(one: string): number;
-  diff(one: string, two: string): number;
-  diff(one: string, two: string, three: boolean): number;
-}
-```
-
-✅ **Do** use optional parameters whenever possible:
-
-```ts
-/* OK */
-interface Example {
-  diff(one: string, two?: string, three?: boolean): number;
-}
-```
-
-Note that this collapsing should only occur when all overloads have the same return type.
-
-❔ **Why:** This is important for two reasons.
-
-TypeScript resolves signature compatibility by seeing if any signature of the target can be invoked with the arguments of the source,
-_and extraneous arguments are allowed_.
-This code, for example, exposes a bug only when the signature is correctly written using optional parameters:
-
-```ts
-function fn(x: (a: string, b: number, c: number) => void) {}
-var x: Example;
-// When written with overloads, OK -- used first overload
-// When written with optionals, correctly an error
-fn(x.diff);
-```
-
-The second reason is when a consumer uses the "strict null checking" feature of TypeScript.
-Because unspecified parameters appear as `undefined` in JavaScript, it's usually fine to pass an explicit `undefined` to a function with optional arguments.
-This code, for example, should be OK under strict nulls:
-
-```ts
-var x: Example;
-// When written with overloads, incorrectly an error because of passing 'undefined' to 'string'
-// When written with optionals, correctly OK
-x.diff("something", true ? undefined : "hour");
-```
-
-## Use Union Types
-
-❌ **Don't** write overloads that differ by type in only one argument position:
-
-```ts
-/* WRONG */
-interface Moment {
-  utcOffset(): number;
-  utcOffset(b: number): Moment;
-  utcOffset(b: string): Moment;
-}
-```
-
-✅ **Do** use union types whenever possible:
-
-```ts
-/* OK */
-interface Moment {
-  utcOffset(): number;
-  utcOffset(b: number | string): Moment;
-}
-```
-
-Note that we didn't make `b` optional here because the return types of the signatures differ.
-
-❔ **Why:** This is important for people who are "passing through" a value to your function:
-
-```ts
-function fn(x: string): void;
-function fn(x: number): void;
-function fn(x: number | string) {
-  // When written with separate overloads, incorrectly an error
-  // When written with union types, correctly OK
-  return moment().utcOffset(x);
-}
-```
diff --git a/docs/documentation/zh/declaration-files/Introduction.md b/docs/documentation/zh/declaration-files/Introduction.md
deleted file mode 100644
index 2b1c9603..00000000
--- a/docs/documentation/zh/declaration-files/Introduction.md
+++ /dev/null
@@ -1,53 +0,0 @@
----
-title: Introduction
-layout: docs
-permalink: /docs/handbook/declaration-files/introduction.html
-oneline: "How to write a high-quality TypeScript Declaration (d.ts) file"
----
-
-The Declaration Files section is designed to teach you how to write a high-quality TypeScript Declaration File. We need to assume basic familiarity with the TypeScript language in order to get started.
-
-If you haven't already, you should read the [TypeScript Handbook](/docs/handbook/2/basic-types.html)
-to familiarize yourself with basic concepts, especially types and modules.
-
-The most common case for learning how .d.ts files work is that you're typing an npm package with no types. 
-In that case, you can jump straight to [Modules .d.ts](/docs/handbook/declaration-files/templates/module-d-ts.html).
-
-The Declaration Files section is broken down into the following sections.
-
-## [Declaration Reference](/docs/handbook/declaration-files/by-example.html)
-
-We are often faced with writing a declaration file when we only have examples of the underlying library to guide us.
-The [Declaration Reference](/docs/handbook/declaration-files/by-example.html) section shows many common API patterns and how to write declarations for each of them.
-This guide is aimed at the TypeScript novice who may not yet be familiar with every language construct in TypeScript.
-
-## [Library Structures](/docs/handbook/declaration-files/library-structures.html)
-
-The [Library Structures](/docs/handbook/declaration-files/library-structures.html) guide helps you understand common library formats and how to write a proper declaration file for each format.
-If you're editing an existing file, you probably don't need to read this section.
-Authors of new declaration files are strongly encouraged to read this section to properly understand how the format of the library influences the writing of the declaration file. 
-
-In the Template section you'll find a number of declaration files that serve as a useful starting point
-when writing a new file. If you already know what your structure is, see the d.ts Template section in the sidebar.
-
-## [Do's and Don'ts](/docs/handbook/declaration-files/do-s-and-don-ts.html)
-
-Many common mistakes in declaration files can be easily avoided.
-The [Do's and Don'ts](/docs/handbook/declaration-files/do-s-and-don-ts.html) section identifies common errors, 
-describes how to detect them, 
-and how to fix them.
-Everyone should read this section to help themselves avoid common mistakes.
-
-## [Deep Dive](/docs/handbook/declaration-files/deep-dive.html)
-
-For seasoned authors interested in the underlying mechanics of how declaration files work, 
-the [Deep Dive](/docs/handbook/declaration-files/deep-dive.html) section explains many advanced concepts in declaration writing, 
-and shows how to leverage these concepts to create cleaner and more intuitive declaration files.
-
-## [Publish to npm](/docs/handbook/declaration-files/publishing.html)
-
-The [Publishing](/docs/handbook/declaration-files/publishing.html) section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages.
-
-## [Find and Install Declaration Files](/docs/handbook/declaration-files/consumption.html)
-
-For JavaScript library users, the [Consumption](/docs/handbook/declaration-files/consumption.html) section offers a few simple steps to locate and install corresponding declaration files.
diff --git a/docs/documentation/zh/declaration-files/Library Structures.md b/docs/documentation/zh/declaration-files/Library Structures.md
deleted file mode 100644
index b2e57311..00000000
--- a/docs/documentation/zh/declaration-files/Library Structures.md	
+++ /dev/null
@@ -1,326 +0,0 @@
----
-title: Library Structures
-layout: docs
-permalink: /docs/handbook/declaration-files/library-structures.html
-oneline: How to structure your d.ts files
----
-
-Broadly speaking, the way you _structure_ your declaration file depends on how the library is consumed.
-There are many ways of offering a library for consumption in JavaScript, and you'll need to write your declaration file to match it.
-This guide covers how to identify common library patterns, and how to write declaration files which correspond to that pattern.
-
-Each type of major library structuring pattern has a corresponding file in the [Templates](/docs/handbook/declaration-files/templates.html) section.
-You can start with these templates to help you get going faster.
-
-## Identifying Kinds of Libraries
-
-First, we'll review the kinds of libraries TypeScript declaration files can represent.
-We'll briefly show how each kind of library is _used_, how it is _written_, and list some example libraries from the real world.
-
-Identifying the structure of a library is the first step in writing its declaration file.
-We'll give hints on how to identify structure both based on its _usage_ and its _code_.
-Depending on the library's documentation and organization, one might be easier than the other.
-We recommend using whichever is more comfortable to you.
-
-## What should you look for?
-
-Question to ask yourself while looking at a library you are trying to type.
-
-1. How do you obtain the library?
-
-   For example, can you _only_ get it through npm or only from a CDN?
-
-2. How would you import it?
-
-   Does it add a global object? Does it use `require` or `import`/`export` statements?
-
-## Smaller samples for different types of libraries
-
-## Modular Libraries
-
-Almost every modern Node.js library falls into the module family.
-These type of libraries only work in a JS environment with a module loader.
-For example, `express` only works in Node.js and must be loaded using the CommonJS `require` function.
-
-ECMAScript 2015 (also known as ES2015, ECMAScript 6, and ES6), CommonJS, and RequireJS have similar notions of _importing_ a _module_.
-In JavaScript CommonJS (Node.js), for example, you would write
-
-```js
-var fs = require("fs");
-```
-
-In TypeScript or ES6, the `import` keyword serves the same purpose:
-
-```ts
-import * as fs from "fs";
-```
-
-You'll typically see modular libraries include one of these lines in their documentation:
-
-```js
-var someLib = require("someLib");
-```
-
-or
-
-```js
-define(..., ['someLib'], function(someLib) {
-
-});
-```
-
-As with global modules, you might see these examples in the documentation of [a UMD](#umd) module, so be sure to check the code or documentation.
-
-### Identifying a Module Library from Code
-
-Modular libraries will typically have at least some of the following:
-
-- Unconditional calls to `require` or `define`
-- Declarations like `import * as a from 'b';` or `export c;`
-- Assignments to `exports` or `module.exports`
-
-They will rarely have:
-
-- Assignments to properties of `window` or `global`
-
-### Templates For Modules
-
-There are four templates available for modules,
-[`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html), [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html), [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html) and [`module-plugin.d.ts`](/docs/handbook/declaration-files/templates/module-plugin-d-ts.html).
-
-You should first read [`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html) for an overview on the way they all work.
-
-Then use the template [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html) if your module can be _called_ like a function:
-
-```js
-const x = require("foo");
-// Note: calling 'x' as a function
-const y = x(42);
-```
-
-Use the template [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html) if your module can be _constructed_ using `new`:
-
-```js
-const x = require("bar");
-// Note: using 'new' operator on the imported variable
-const y = new x("hello");
-```
-
-If you have a module which when imported, makes changes to other modules use template [`module-plugin.d.ts`](/docs/handbook/declaration-files/templates/module-plugin-d-ts.html):
-
-```js
-const jest = require("jest");
-require("jest-matchers-files");
-```
-
-## Global Libraries
-
-A _global_ library is one that can be accessed from the global scope (i.e. without using any form of `import`).
-Many libraries simply expose one or more global variables for use.
-For example, if you were using [jQuery](https://jquery.com/), the `$` variable can be used by simply referring to it:
-
-```ts
-$(() => {
-  console.log("hello!");
-});
-```
-
-You'll usually see guidance in the documentation of a global library of how to use the library in an HTML script tag:
-
-```html
-
-```
-
-Today, most popular globally-accessible libraries are actually written as UMD libraries (see below).
-UMD library documentation is hard to distinguish from global library documentation.
-Before writing a global declaration file, make sure the library isn't actually UMD.
-
-### Identifying a Global Library from Code
-
-Global library code is usually extremely simple.
-A global "Hello, world" library might look like this:
-
-```js
-function createGreeting(s) {
-  return "Hello, " + s;
-}
-```
-
-or like this:
-
-```js
-// Web
-window.createGreeting = function (s) {
-  return "Hello, " + s;
-};
-
-// Node
-global.createGreeting = function (s) {
-  return "Hello, " + s;
-};
-
-// Potentially any runtime
-globalThis.createGreeting = function (s) {
-  return "Hello, " + s;
-};
-```
-
-When looking at the code of a global library, you'll usually see:
-
-- Top-level `var` statements or `function` declarations
-- One or more assignments to `window.someName`
-- Assumptions that DOM primitives like `document` or `window` exist
-
-You _won't_ see:
-
-- Checks for, or usage of, module loaders like `require` or `define`
-- CommonJS/Node.js-style imports of the form `var fs = require("fs");`
-- Calls to `define(...)`
-- Documentation describing how to `require` or import the library
-
-### Examples of Global Libraries
-
-Because it's usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style.
-However, libraries that are small and require the DOM (or have _no_ dependencies) may still be global.
-
-### Global Library Template
-
-The template file [`global.d.ts`](/docs/handbook/declaration-files/templates/global-plugin-d-ts.html) defines an example library `myLib`.
-Be sure to read the ["Preventing Name Conflicts" footnote](#preventing-name-conflicts).
-
-## _UMD_
-
-A _UMD_ module is one that can _either_ be used as module (through an import), or as a global (when run in an environment without a module loader).
-Many popular libraries, such as [Moment.js](http://momentjs.com/), are written this way.
-For example, in Node.js or using RequireJS, you would write:
-
-```ts
-import moment = require("moment");
-console.log(moment.format());
-```
-
-whereas in a vanilla browser environment you would write:
-
-```js
-console.log(moment.format());
-```
-
-### Identifying a UMD library
-
-[UMD modules](https://github.com/umdjs/umd) check for the existence of a module loader environment.
-This is an easy-to-spot pattern that looks something like this:
-
-```js
-(function (root, factory) {
-    if (typeof define === "function" && define.amd) {
-        define(["libName"], factory);
-    } else if (typeof module === "object" && module.exports) {
-        module.exports = factory(require("libName"));
-    } else {
-        root.returnExports = factory(root.libName);
-    }
-}(this, function (b) {
-```
-
-If you see tests for `typeof define`, `typeof window`, or `typeof module` in the code of a library, especially at the top of the file, it's almost always a UMD library.
-
-Documentation for UMD libraries will also often demonstrate a "Using in Node.js" example showing `require`,
-and a "Using in the browser" example showing using a `
-```
-
-Today, most popular globally-accessible libraries are actually written as UMD libraries (see below).
-UMD library documentation is hard to distinguish from global library documentation.
-Before writing a global declaration file, make sure the library isn't actually UMD.
-
-## Identifying a Global Library from Code
-
-Global library code is usually extremely simple.
-A global "Hello, world" library might look like this:
-
-```js
-function createGreeting(s) {
-  return "Hello, " + s;
-}
-```
-
-or like this:
-
-```js
-window.createGreeting = function (s) {
-  return "Hello, " + s;
-};
-```
-
-When looking at the code of a global library, you'll usually see:
-
-- Top-level `var` statements or `function` declarations
-- One or more assignments to `window.someName`
-- Assumptions that DOM primitives like `document` or `window` exist
-
-You _won't_ see:
-
-- Checks for, or usage of, module loaders like `require` or `define`
-- CommonJS/Node.js-style imports of the form `var fs = require("fs");`
-- Calls to `define(...)`
-- Documentation describing how to `require` or import the library
-
-## Examples of Global Libraries
-
-Because it's usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style.
-However, libraries that are small and require the DOM (or have _no_ dependencies) may still be global.
-
-## Global Library Template
-
-You can see an example DTS below:
-
-```ts
-// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
-// Project: [~THE PROJECT NAME~]
-// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
-
-/*~ If this library is callable (e.g. can be invoked as myLib(3)),
- *~ include those call signatures here.
- *~ Otherwise, delete this section.
- */
-declare function myLib(a: string): string;
-declare function myLib(a: number): number;
-
-/*~ If you want the name of this library to be a valid type name,
- *~ you can do so here.
- *~
- *~ For example, this allows us to write 'var x: myLib';
- *~ Be sure this actually makes sense! If it doesn't, just
- *~ delete this declaration and add types inside the namespace below.
- */
-interface myLib {
-  name: string;
-  length: number;
-  extras?: string[];
-}
-
-/*~ If your library has properties exposed on a global variable,
- *~ place them here.
- *~ You should also place types (interfaces and type alias) here.
- */
-declare namespace myLib {
-  //~ We can write 'myLib.timeout = 50;'
-  let timeout: number;
-
-  //~ We can access 'myLib.version', but not change it
-  const version: string;
-
-  //~ There's some class we can create via 'let c = new myLib.Cat(42)'
-  //~ Or reference e.g. 'function f(c: myLib.Cat) { ... }
-  class Cat {
-    constructor(n: number);
-
-    //~ We can read 'c.age' from a 'Cat' instance
-    readonly age: number;
-
-    //~ We can invoke 'c.purr()' from a 'Cat' instance
-    purr(): void;
-  }
-
-  //~ We can declare a variable as
-  //~   'var s: myLib.CatSettings = { weight: 5, name: "Maru" };'
-  interface CatSettings {
-    weight: number;
-    name: string;
-    tailLength?: number;
-  }
-
-  //~ We can write 'const v: myLib.VetID = 42;'
-  //~  or 'const v: myLib.VetID = "bob";'
-  type VetID = string | number;
-
-  //~ We can invoke 'myLib.checkCat(c)' or 'myLib.checkCat(c, v);'
-  function checkCat(c: Cat, s?: VetID);
-}
-```
diff --git a/docs/documentation/zh/declaration-files/templates/module-class.d.ts.md b/docs/documentation/zh/declaration-files/templates/module-class.d.ts.md
deleted file mode 100644
index 4825b594..00000000
--- a/docs/documentation/zh/declaration-files/templates/module-class.d.ts.md
+++ /dev/null
@@ -1,83 +0,0 @@
----
-title: "Module: Class"
-layout: docs
-permalink: /docs/handbook/declaration-files/templates/module-class-d-ts.html
----
-
-
-
-For example, when you want to work with JavaScript code which looks like:
-
-```ts
-const Greeter = require("super-greeter");
-
-const greeter = new Greeter();
-greeter.greet();
-```
-
-To handle both importing via UMD and modules:
-
-```ts
-// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
-// Project: [~THE PROJECT NAME~]
-// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
-
-/*~ This is the module template file for class modules.
- *~ You should rename it to index.d.ts and place it in a folder with the same name as the module.
- *~ For example, if you were writing a file for "super-greeter", this
- *~ file should be 'super-greeter/index.d.ts'
- */
-
-// Note that ES6 modules cannot directly export class objects.
-// This file should be imported using the CommonJS-style:
-//   import x = require('[~THE MODULE~]');
-//
-// Alternatively, if --allowSyntheticDefaultImports or
-// --esModuleInterop is turned on, this file can also be
-// imported as a default import:
-//   import x from '[~THE MODULE~]';
-//
-// Refer to the TypeScript documentation at
-// https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require
-// to understand common workarounds for this limitation of ES6 modules.
-
-/*~ If this module is a UMD module that exposes a global variable 'myClassLib' when
- *~ loaded outside a module loader environment, declare that global here.
- *~ Otherwise, delete this declaration.
- */
-export as namespace "super-greeter";
-
-/*~ This declaration specifies that the class constructor function
- *~ is the exported object from the file
- */
-export = Greeter;
-
-/*~ Write your module's methods and properties in this class */
-declare class Greeter {
-  constructor(customGreeting?: string);
-
-  greet: void;
-
-  myMethod(opts: MyClass.MyClassMethodOptions): number;
-}
-
-/*~ If you want to expose types from your module as well, you can
- *~ place them in this block.
- *~
- *~ Note that if you decide to include this namespace, the module can be
- *~ incorrectly imported as a namespace object, unless
- *~ --esModuleInterop is turned on:
- *~   import * as x from '[~THE MODULE~]'; // WRONG! DO NOT DO THIS!
- */
-declare namespace MyClass {
-  export interface MyClassMethodOptions {
-    width?: number;
-    height?: number;
-  }
-}
-```
diff --git a/docs/documentation/zh/declaration-files/templates/module-function.d.ts.md b/docs/documentation/zh/declaration-files/templates/module-function.d.ts.md
deleted file mode 100644
index fde9ddf6..00000000
--- a/docs/documentation/zh/declaration-files/templates/module-function.d.ts.md
+++ /dev/null
@@ -1,85 +0,0 @@
----
-title: "Module: Function"
-layout: docs
-permalink: /docs/handbook/declaration-files/templates/module-function-d-ts.html
----
-
-For example, when you want to work with JavaScript code which looks like:
-
-```ts
-import greeter from "super-greeter";
-
-greeter(2);
-greeter("Hello world");
-```
-
-To handle both importing via UMD and modules:
-
-```ts
-// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
-// Project: [~THE PROJECT NAME~]
-// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
-
-/*~ This is the module template file for function modules.
- *~ You should rename it to index.d.ts and place it in a folder with the same name as the module.
- *~ For example, if you were writing a file for "super-greeter", this
- *~ file should be 'super-greeter/index.d.ts'
- */
-
-// Note that ES6 modules cannot directly export class objects.
-// This file should be imported using the CommonJS-style:
-//   import x = require('[~THE MODULE~]');
-//
-// Alternatively, if --allowSyntheticDefaultImports or
-// --esModuleInterop is turned on, this file can also be
-// imported as a default import:
-//   import x from '[~THE MODULE~]';
-//
-// Refer to the TypeScript documentation at
-// https://www.typescriptlang.org/docs/handbook/modules.html#export--and-import--require
-// to understand common workarounds for this limitation of ES6 modules.
-
-/*~ If this module is a UMD module that exposes a global variable 'myFuncLib' when
- *~ loaded outside a module loader environment, declare that global here.
- *~ Otherwise, delete this declaration.
- */
-export as namespace myFuncLib;
-
-/*~ This declaration specifies that the function
- *~ is the exported object from the file
- */
-export = Greeter;
-
-/*~ This example shows how to have multiple overloads for your function */
-declare function Greeter(name: string): Greeter.NamedReturnType;
-declare function Greeter(length: number): Greeter.LengthReturnType;
-
-/*~ If you want to expose types from your module as well, you can
- *~ place them in this block. Often you will want to describe the
- *~ shape of the return type of the function; that type should
- *~ be declared in here, as this example shows.
- *~
- *~ Note that if you decide to include this namespace, the module can be
- *~ incorrectly imported as a namespace object, unless
- *~ --esModuleInterop is turned on:
- *~   import * as x from '[~THE MODULE~]'; // WRONG! DO NOT DO THIS!
- */
-declare namespace Greeter {
-  export interface LengthReturnType {
-    width: number;
-    height: number;
-  }
-  export interface NamedReturnType {
-    firstName: string;
-    lastName: string;
-  }
-
-  /*~ If the module also has properties, declare them here. For example,
-   *~ this declaration says that this code is legal:
-   *~   import f = require('super-greeter');
-   *~   console.log(f.defaultName);
-   */
-  export const defaultName: string;
-  export let defaultLength: number;
-}
-```
diff --git a/docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md b/docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md
deleted file mode 100644
index c150521f..00000000
--- a/docs/documentation/zh/declaration-files/templates/module-plugin.d.ts.md
+++ /dev/null
@@ -1,67 +0,0 @@
----
-title: "Module: Plugin"
-layout: docs
-permalink: /docs/handbook/declaration-files/templates/module-plugin-d-ts.html
----
-
-For example, when you want to work with JavaScript code which extends another library.
-
-```ts
-import { greeter } from "super-greeter";
-
-// Normal Greeter API
-greeter(2);
-greeter("Hello world");
-
-// Now we extend the object with a new function at runtime
-import "hyper-super-greeter";
-greeter.hyperGreet();
-```
-
-The definition for "super-greeter":
-
-```ts
-/*~ This example shows how to have multiple overloads for your function */
-export interface GreeterFunction {
-  (name: string): void
-  (time: number): void
-}
-
-/*~ This example shows how to export a function specified by an interface */
-export const greeter: GreeterFunction;
-```
-
-We can extend the existing module like the following:
-
-```ts
-// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
-// Project: [~THE PROJECT NAME~]
-// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
-
-/*~ This is the module plugin template file. You should rename it to index.d.ts
- *~ and place it in a folder with the same name as the module.
- *~ For example, if you were writing a file for "super-greeter", this
- *~ file should be 'super-greeter/index.d.ts'
- */
-
-/*~ On this line, import the module which this module adds to */
-import { greeter } from "super-greeter";
-
-/*~ Here, declare the same module as the one you imported above
- *~ then we expand the existing declaration of the greeter function
- */
-export module "super-greeter" {
-  export interface GreeterFunction {
-    /** Greets even better! */
-    hyperGreet(): void;
-  }
-}
-```
-
-This uses [declaration merging](/docs/handbook/declaration-merging.html)
-
-## The Impact of ES6 on Module Plugins
-
-Some plugins add or modify top-level exports on existing modules.
-While this is legal in CommonJS and other loaders, ES6 modules are considered immutable and this pattern will not be possible.
-Because TypeScript is loader-agnostic, there is no compile-time enforcement of this policy, but developers intending to transition to an ES6 module loader should be aware of this.
diff --git a/docs/documentation/zh/declaration-files/templates/module.d.ts.md b/docs/documentation/zh/declaration-files/templates/module.d.ts.md
deleted file mode 100644
index aa83daf1..00000000
--- a/docs/documentation/zh/declaration-files/templates/module.d.ts.md
+++ /dev/null
@@ -1,311 +0,0 @@
----
-title: Modules .d.ts
-layout: docs
-permalink: /docs/handbook/declaration-files/templates/module-d-ts.html
----
-
-## Comparing JavaScript to an example DTS
-
-## Common CommonJS Patterns
-
-A module using CommonJS patterns uses `module.exports` to describe the exported values. For example, here is a module which exports a function and a numerical constant:
-
-```js
-const maxInterval = 12;
-
-function getArrayLength(arr) {
-  return arr.length;
-}
-
-module.exports = {
-  getArrayLength,
-  maxInterval,
-};
-```
-
-This can be described by the following `.d.ts`:
-
-```ts
-export function getArrayLength(arr: any[]): number;
-export const maxInterval: 12;
-```
-
-The TypeScript playground can show you the `.d.ts` equivalent for JavaScript code. You can [try it yourself here](/play?useJavaScript=true#code/GYVwdgxgLglg9mABAcwKZQIICcsEMCeAMqmMlABYAUuOAlIgN6IBQiiW6IWSNWAdABsSZcswC+zCAgDOURAFtcADwAq5GKUQBeRAEYATM2by4AExBC+qJQAc4WKNO2NWKdNjxFhFADSvFquqk4sxAA).
-
-The `.d.ts` syntax intentionally looks like [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) syntax.
-ES Modules was ratified by TC39 in 2019, while it has been available via transpilers for a long time, however if you have a JavaScript codebase using ES Modules:
-
-```js
-export function getArrayLength(arr) {
-  return arr.length;
-}
-```
-
-This would have the following `.d.ts` equivalent:
-
-```ts
-export function getArrayLength(arr: any[]): number;
-```
-
-### Default Exports
-
-In CommonJS you can export any value as the default export, for example here is a regular expression module:
-
-```js
-module.exports = /hello( world)?/;
-```
-
-Which can be described by the following .d.ts:
-
-```ts
-declare const helloWorld: RegExp;
-export default helloWorld;
-```
-
-Or a number:
-
-```js
-module.exports = 3.142;
-```
-
-```ts
-declare const pi: number;
-export default pi;
-```
-
-One style of exporting in CommonJS is to export a function.
-Because a function is also an object, then extra fields can be added and are included in the export.
-
-```js
-function getArrayLength(arr) {
-  return arr.length;
-}
-getArrayLength.maxInterval = 12;
-
-module.exports = getArrayLength;
-```
-
-Which can be described with:
-
-```ts
-export default function getArrayLength(arr: any[]): number;
-export const maxInterval: 12;
-```
-
-Note that using `export default` in your .d.ts files requires [`esModuleInterop: true`](/tsconfig#esModuleInterop) to work.
-If you can't have `esModuleInterop: true` in your project, such as when you're submitting a PR to Definitely Typed, you'll have to use the `export=` syntax instead. This older syntax is harder to use but works everywhere.
-Here's how the above example would have to be written using `export=`:
-
-```ts
-declare function getArrayLength(arr: any[]): number;
-declare namespace getArrayLength {
-  declare const maxInterval: 12;
-}
-
-export = getArrayLength;
-```
-
-See [Module: Functions](/docs/handbook/declaration-files/templates/module-function-d-ts.html) for details of how that works, and the [Modules reference](/docs/handbook/modules.html) page.
-
-## Handling Many Consuming Import
-
-There are many ways to import a module in modern consuming code:
-
-```ts
-const fastify = require("fastify");
-const { fastify } = require("fastify");
-import fastify = require("fastify");
-import * as Fastify from "fastify";
-import { fastify, FastifyInstance } from "fastify";
-import fastify from "fastify";
-import fastify, { FastifyInstance } from "fastify";
-```
-
-Covering all of these cases requires the JavaScript code to actually support all of these patterns.
-To support many of these patterns, a CommonJS module would need to look something like:
-
-```js
-class FastifyInstance {}
-
-function fastify() {
-  return new FastifyInstance();
-}
-
-fastify.FastifyInstance = FastifyInstance;
-
-// Allows for { fastify }
-fastify.fastify = fastify;
-// Allows for strict ES Module support
-fastify.default = fastify;
-// Sets the default export
-module.exports = fastify;
-```
-
-## Types in Modules
-
-You may want to provide a type for JavaScript code which does not exist
-
-```js
-function getArrayMetadata(arr) {
-  return {
-    length: getArrayLength(arr),
-    firstObject: arr[0],
-  };
-}
-
-module.exports = {
-  getArrayMetadata,
-};
-```
-
-This can be described with:
-
-```ts
-export type ArrayMetadata = {
-  length: number;
-  firstObject: any | undefined;
-};
-export function getArrayMetadata(arr: any[]): ArrayMetadata;
-```
-
-This example is a good case for [using generics](/docs/handbook/generics.html#generic-types) to provide richer type information:
-
-```ts
-export type ArrayMetadata = {
-  length: number;
-  firstObject: ArrType | undefined;
-};
-
-export function getArrayMetadata(
-  arr: ArrType[]
-): ArrayMetadata;
-```
-
-Now the type of the array propagates into the `ArrayMetadata` type.
-
-The types which are exported can then be re-used by consumers of the modules using either `import` or `import type` in TypeScript code or [JSDoc imports](/docs/handbook/jsdoc-supported-types.html#import-types).
-
-### Namespaces in Module Code
-
-Trying to describe the runtime relationship of JavaScript code can be tricky.
-When the ES Module-like syntax doesn't provide enough tools to describe the exports then you can use `namespaces`.
-
-For example, you may have complex enough types to describe that you choose to namespace them inside your `.d.ts`:
-
-```ts
-// This represents the JavaScript class which would be available at runtime
-export class API {
-  constructor(baseURL: string);
-  getInfo(opts: API.InfoRequest): API.InfoResponse;
-}
-
-// This namespace is merged with the API class and allows for consumers, and this file
-// to have types which are nested away in their own sections.
-declare namespace API {
-  export interface InfoRequest {
-    id: string;
-  }
-
-  export interface InfoResponse {
-    width: number;
-    height: number;
-  }
-}
-```
-
-To understand how namespaces work in `.d.ts` files read the [`.d.ts` deep dive](/docs/handbook/declaration-files/deep-dive.html).
-
-### Optional Global Usage
-
-You can use `export as namespace` to declare that your module will be available in the global scope in UMD contexts:
-
-```ts
-export as namespace moduleName;
-```
-
-## Reference Example
-
-To give you an idea of how all these pieces can come together, here is a reference `.d.ts` to start with when making a new module
-
-```ts
-// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
-// Project: [~THE PROJECT NAME~]
-// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
-
-/*~ This is the module template file. You should rename it to index.d.ts
- *~ and place it in a folder with the same name as the module.
- *~ For example, if you were writing a file for "super-greeter", this
- *~ file should be 'super-greeter/index.d.ts'
- */
-
-/*~ If this module is a UMD module that exposes a global variable 'myLib' when
- *~ loaded outside a module loader environment, declare that global here.
- *~ Otherwise, delete this declaration.
- */
-export as namespace myLib;
-
-/*~ If this module exports functions, declare them like so.
- */
-export function myFunction(a: string): string;
-export function myOtherFunction(a: number): number;
-
-/*~ You can declare types that are available via importing the module */
-export interface SomeType {
-  name: string;
-  length: number;
-  extras?: string[];
-}
-
-/*~ You can declare properties of the module using const, let, or var */
-export const myField: number;
-```
-
-### Library file layout
-
-The layout of your declaration files should mirror the layout of the library.
-
-A library can consist of multiple modules, such as
-
-```
-myLib
-  +---- index.js
-  +---- foo.js
-  +---- bar
-         +---- index.js
-         +---- baz.js
-```
-
-These could be imported as
-
-```js
-var a = require("myLib");
-var b = require("myLib/foo");
-var c = require("myLib/bar");
-var d = require("myLib/bar/baz");
-```
-
-Your declaration files should thus be
-
-```
-@types/myLib
-  +---- index.d.ts
-  +---- foo.d.ts
-  +---- bar
-         +---- index.d.ts
-         +---- baz.d.ts
-```
-
-### Testing your types
-
-If you are planning on submitting these changes to DefinitelyTyped for everyone to also use, then we recommend you:
-
-> 1. Create a new folder in `node_modules/@types/[libname]`
-> 2. Create an `index.d.ts` in that folder, and copy the example in
-> 3. See where your usage of the module breaks, and start to fill out the index.d.ts
-> 4. When you're happy, clone [DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped) and follow the instructions in the README. 
-
-Otherwise
-
-> 1. Create a new file in the root of your source tree: `[libname].d.ts`
-> 2. Add `declare module "[libname]" {  }`
-> 3. Add the template inside the braces of the declare module, and see where your usage breaks 
diff --git a/docs/documentation/zh/get-started/TS for Functional Programmers.md b/docs/documentation/zh/get-started/TS for Functional Programmers.md
deleted file mode 100644
index 1721a141..00000000
--- a/docs/documentation/zh/get-started/TS for Functional Programmers.md	
+++ /dev/null
@@ -1,597 +0,0 @@
----
-title: TypeScript for Functional Programmers
-short: TS for Functional Programmers
-layout: docs
-permalink: /docs/handbook/typescript-in-5-minutes-func.html
-oneline: Learn TypeScript if you have a background in functional programming
----
-
-TypeScript began its life as an attempt to bring traditional object-oriented types
-to JavaScript so that the programmers at Microsoft could bring
-traditional object-oriented programs to the web. As it has developed, TypeScript's type
-system has evolved to model code written by native JavaScripters. The
-resulting system is powerful, interesting and messy.
-
-This introduction is designed for working Haskell or ML programmers
-who want to learn TypeScript. It describes how the type system of
-TypeScript differs from Haskell's type system. It also describes
-unique features of TypeScript's type system that arise from its
-modelling of JavaScript code.
-
-This introduction does not cover object-oriented programming. In
-practice, object-oriented programs in TypeScript are similar to those
-in other popular languages with OO features.
-
-## Prerequisites
-
-In this introduction, I assume you know the following:
-
-- How to program in JavaScript, the good parts.
-- Type syntax of a C-descended language.
-
-If you need to learn the good parts of JavaScript, read
-[JavaScript: The Good Parts](http://shop.oreilly.com/product/9780596517748.do).
-You may be able to skip the book if you know how to write programs in
-a call-by-value lexically scoped language with lots of mutability and
-not much else.
-[R4RS Scheme](https://people.csail.mit.edu/jaffer/r4rs.pdf) is a good example.
-
-[The C++ Programming Language](http://www.stroustrup.com/4th.html) is
-a good place to learn about C-style type syntax. Unlike C++,
-TypeScript uses postfix types, like so: `x: string` instead of `string x`.
-
-## Concepts not in Haskell
-
-## Built-in types
-
-JavaScript defines 8 built-in types:
-
-| Type        | Explanation                                 |
-| ----------- | ------------------------------------------- |
-| `Number`    | a double-precision IEEE 754 floating point. |
-| `String`    | an immutable UTF-16 string.                 |
-| `BigInt`    | integers in the arbitrary precision format. |
-| `Boolean`   | `true` and `false`.                         |
-| `Symbol`    | a unique value usually used as a key.       |
-| `Null`      | equivalent to the unit type.                |
-| `Undefined` | also equivalent to the unit type.           |
-| `Object`    | similar to records.                         |
-
-[See the MDN page for more detail](https://developer.mozilla.org/docs/Web/JavaScript/Data_structures).
-
-TypeScript has corresponding primitive types for the built-in types:
-
-- `number`
-- `string`
-- `bigint`
-- `boolean`
-- `symbol`
-- `null`
-- `undefined`
-- `object`
-
-### Other important TypeScript types
-
-| Type           | Explanation                                                 |
-| -------------- | ----------------------------------------------------------- |
-| `unknown`      | the top type.                                               |
-| `never`        | the bottom type.                                            |
-| object literal | eg `{ property: Type }`                                     |
-| `void`         | a subtype of `undefined` intended for use as a return type. |
-| `T[]`          | mutable arrays, also written `Array`                     |
-| `[T, T]`       | tuples, which are fixed-length but mutable                  |
-| `(t: T) => U`  | functions                                                   |
-
-Notes:
-
-1. Function syntax includes parameter names. This is pretty hard to get used to!
-
-   ```ts
-   let fst: (a: any, b: any) => any = (a, b) => a;
-
-   // or more precisely:
-
-   let fst: (a: T, b: U) => T = (a, b) => a;
-   ```
-
-2. Object literal type syntax closely mirrors object literal value syntax:
-
-   ```ts
-   let o: { n: number; xs: object[] } = { n: 1, xs: [] };
-   ```
-
-3. `[T, T]` is a subtype of `T[]`. This is different than Haskell, where tuples are not related to lists.
-
-### Boxed types
-
-JavaScript has boxed equivalents of primitive types that contain the
-methods that programmers associate with those types. TypeScript
-reflects this with, for example, the difference between the primitive
-type `number` and the boxed type `Number`. The boxed types are rarely
-needed, since their methods return primitives.
-
-```ts
-(1).toExponential();
-// equivalent to
-Number.prototype.toExponential.call(1);
-```
-
-Note that calling a method on a numeric literal requires it to be in
-parentheses to aid the parser.
-
-## Gradual typing
-
-TypeScript uses the type `any` whenever it can't tell what the type of
-an expression should be. Compared to `Dynamic`, calling `any` a type
-is an overstatement. It just turns off the type checker
-wherever it appears. For example, you can push any value into an
-`any[]` without marking the value in any way:
-
-```ts twoslash
-// with "noImplicitAny": false in tsconfig.json, anys: any[]
-const anys = [];
-anys.push(1);
-anys.push("oh no");
-anys.push({ anything: "goes" });
-```
-
-And you can use an expression of type `any` anywhere:
-
-```ts
-anys.map(anys[1]); // oh no, "oh no" is not a function
-```
-
-`any` is contagious, too — if you initialise a variable with an
-expression of type `any`, the variable has type `any` too.
-
-```ts
-let sepsis = anys[0] + anys[1]; // this could mean anything
-```
-
-To get an error when TypeScript produces an `any`, use
-`"noImplicitAny": true`, or `"strict": true` in `tsconfig.json`.
-
-## Structural typing
-
-Structural typing is a familiar concept to most functional
-programmers, although Haskell and most MLs are not
-structurally typed. Its basic form is pretty simple:
-
-```ts
-// @strict: false
-let o = { x: "hi", extra: 1 }; // ok
-let o2: { x: string } = o; // ok
-```
-
-Here, the object literal `{ x: "hi", extra: 1 }` has a matching
-literal type `{ x: string, extra: number }`. That
-type is assignable to `{ x: string }` since
-it has all the required properties and those properties have
-assignable types. The extra property doesn't prevent assignment, it
-just makes it a subtype of `{ x: string }`.
-
-Named types just give a name to a type; for assignability purposes
-there's no difference between the type alias `One` and the interface
-type `Two` below. They both have a property `p: string`. (Type aliases
-behave differently from interfaces with respect to recursive
-definitions and type parameters, however.)
-
-```ts twoslash
-// @errors: 2322
-type One = { p: string };
-interface Two {
-  p: string;
-}
-class Three {
-  p = "Hello";
-}
-
-let x: One = { p: "hi" };
-let two: Two = x;
-two = new Three();
-```
-
-## Unions
-
-In TypeScript, union types are untagged. In other words, they are not
-discriminated unions like `data` in Haskell. However, you can often
-discriminate types in a union using built-in tags or other properties.
-
-```ts twoslash
-function start(
-  arg: string | string[] | (() => string) | { s: string }
-): string {
-  // this is super common in JavaScript
-  if (typeof arg === "string") {
-    return commonCase(arg);
-  } else if (Array.isArray(arg)) {
-    return arg.map(commonCase).join(",");
-  } else if (typeof arg === "function") {
-    return commonCase(arg());
-  } else {
-    return commonCase(arg.s);
-  }
-
-  function commonCase(s: string): string {
-    // finally, just convert a string to another string
-    return s;
-  }
-}
-```
-
-`string`, `Array` and `Function` have built-in type predicates,
-conveniently leaving the object type for the `else` branch. It is
-possible, however, to generate unions that are difficult to
-differentiate at runtime. For new code, it's best to build only
-discriminated unions.
-
-The following types have built-in predicates:
-
-| Type      | Predicate                          |
-| --------- | ---------------------------------- |
-| string    | `typeof s === "string"`            |
-| number    | `typeof n === "number"`            |
-| bigint    | `typeof m === "bigint"`            |
-| boolean   | `typeof b === "boolean"`           |
-| symbol    | `typeof g === "symbol"`            |
-| undefined | `typeof undefined === "undefined"` |
-| function  | `typeof f === "function"`          |
-| array     | `Array.isArray(a)`                 |
-| object    | `typeof o === "object"`            |
-
-Note that functions and arrays are objects at runtime, but have their
-own predicates.
-
-### Intersections
-
-In addition to unions, TypeScript also has intersections:
-
-```ts twoslash
-type Combined = { a: number } & { b: string };
-type Conflicting = { a: number } & { a: string };
-```
-
-`Combined` has two properties, `a` and `b`, just as if they had been
-written as one object literal type. Intersection and union are
-recursive in case of conflicts, so `Conflicting.a: number & string`.
-
-## Unit types
-
-Unit types are subtypes of primitive types that contain exactly one
-primitive value. For example, the string `"foo"` has the type
-`"foo"`. Since JavaScript has no built-in enums, it is common to use a set of
-well-known strings instead. Unions of string literal types allow
-TypeScript to type this pattern:
-
-```ts twoslash
-declare function pad(s: string, n: number, direction: "left" | "right"): string;
-pad("hi", 10, "left");
-```
-
-When needed, the compiler _widens_ — converts to a
-supertype — the unit type to the primitive type, such as `"foo"`
-to `string`. This happens when using mutability, which can hamper some
-uses of mutable variables:
-
-```ts twoslash
-// @errors: 2345
-declare function pad(s: string, n: number, direction: "left" | "right"): string;
-// ---cut---
-let s = "right";
-pad("hi", 10, s); // error: 'string' is not assignable to '"left" | "right"'
-```
-
-Here's how the error happens:
-
-- `"right": "right"`
-- `s: string` because `"right"` widens to `string` on assignment to a mutable variable.
-- `string` is not assignable to `"left" | "right"`
-
-You can work around this with a type annotation for `s`, but that
-in turn prevents assignments to `s` of variables that are not of type
-`"left" | "right"`.
-
-```ts twoslash
-declare function pad(s: string, n: number, direction: "left" | "right"): string;
-// ---cut---
-let s: "left" | "right" = "right";
-pad("hi", 10, s);
-```
-
-## Concepts similar to Haskell
-
-## Contextual typing
-
-TypeScript has some obvious places where it can infer types, like
-variable declarations:
-
-```ts twoslash
-let s = "I'm a string!";
-```
-
-But it also infers types in a few other places that you may not expect
-if you've worked with other C-syntax languages:
-
-```ts twoslash
-declare function map(f: (t: T) => U, ts: T[]): U[];
-let sns = map((n) => n.toString(), [1, 2, 3]);
-```
-
-Here, `n: number` in this example also, despite the fact that `T` and `U`
-have not been inferred before the call. In fact, after `[1,2,3]` has
-been used to infer `T=number`, the return type of `n => n.toString()`
-is used to infer `U=string`, causing `sns` to have the type
-`string[]`.
-
-Note that inference will work in any order, but intellisense will only
-work left-to-right, so TypeScript prefers to declare `map` with the
-array first:
-
-```ts twoslash
-declare function map(ts: T[], f: (t: T) => U): U[];
-```
-
-Contextual typing also works recursively through object literals, and
-on unit types that would otherwise be inferred as `string` or
-`number`. And it can infer return types from context:
-
-```ts twoslash
-declare function run(thunk: (t: T) => void): T;
-let i: { inference: string } = run((o) => {
-  o.inference = "INSERT STATE HERE";
-});
-```
-
-The type of `o` is determined to be `{ inference: string }` because
-
-1. Declaration initialisers are contextually typed by the
-   declaration's type: `{ inference: string }`.
-2. The return type of a call uses the contextual type for inferences,
-   so the compiler infers that `T={ inference: string }`.
-3. Arrow functions use the contextual type to type their parameters,
-   so the compiler gives `o: { inference: string }`.
-
-And it does so while you are typing, so that after typing `o.`, you
-get completions for the property `inference`, along with any other
-properties you'd have in a real program.
-Altogether, this feature can make TypeScript's inference look a bit
-like a unifying type inference engine, but it is not.
-
-## Type aliases
-
-Type aliases are mere aliases, just like `type` in Haskell. The
-compiler will attempt to use the alias name wherever it was used in
-the source code, but does not always succeed.
-
-```ts twoslash
-type Size = [number, number];
-let x: Size = [101.1, 999.9];
-```
-
-The closest equivalent to `newtype` is a _tagged intersection_:
-
-```ts
-type FString = string & { __compileTimeOnly: any };
-```
-
-An `FString` is just like a normal string, except that the compiler
-thinks it has a property named `__compileTimeOnly` that doesn't
-actually exist. This means that `FString` can still be assigned to
-`string`, but not the other way round.
-
-## Discriminated Unions
-
-The closest equivalent to `data` is a union of types with discriminant
-properties, normally called discriminated unions in TypeScript:
-
-```ts
-type Shape =
-  | { kind: "circle"; radius: number }
-  | { kind: "square"; x: number }
-  | { kind: "triangle"; x: number; y: number };
-```
-
-Unlike Haskell, the tag, or discriminant, is just a property in each
-object type. Each variant has an identical property with a different
-unit type. This is still a normal union type; the leading `|` is
-an optional part of the union type syntax. You can discriminate the
-members of the union using normal JavaScript code:
-
-```ts twoslash
-type Shape =
-  | { kind: "circle"; radius: number }
-  | { kind: "square"; x: number }
-  | { kind: "triangle"; x: number; y: number };
-
-function area(s: Shape) {
-  if (s.kind === "circle") {
-    return Math.PI * s.radius * s.radius;
-  } else if (s.kind === "square") {
-    return s.x * s.x;
-  } else {
-    return (s.x * s.y) / 2;
-  }
-}
-```
-
-Note that the return type of `area` is inferred to be `number` because
-TypeScript knows the function is total. If some variant is not
-covered, the return type of `area` will be `number | undefined` instead.
-
-Also, unlike Haskell, common properties show up in any union, so you
-can usefully discriminate multiple members of the union:
-
-```ts twoslash
-type Shape =
-  | { kind: "circle"; radius: number }
-  | { kind: "square"; x: number }
-  | { kind: "triangle"; x: number; y: number };
-// ---cut---
-function height(s: Shape) {
-  if (s.kind === "circle") {
-    return 2 * s.radius;
-  } else {
-    // s.kind: "square" | "triangle"
-    return s.x;
-  }
-}
-```
-
-## Type Parameters
-
-Like most C-descended languages, TypeScript requires declaration of
-type parameters:
-
-```ts
-function liftArray(t: T): Array {
-  return [t];
-}
-```
-
-There is no case requirement, but type parameters are conventionally
-single uppercase letters. Type parameters can also be constrained to a
-type, which behaves a bit like type class constraints:
-
-```ts
-function firstish(t1: T, t2: T): T {
-  return t1.length > t2.length ? t1 : t2;
-}
-```
-
-TypeScript can usually infer type arguments from a call based on the
-type of the arguments, so type arguments are usually not needed.
-
-Because TypeScript is structural, it doesn't need type parameters as
-much as nominal systems. Specifically, they are not needed to make a
-function polymorphic. Type parameters should only be used to
-_propagate_ type information, such as constraining parameters to be
-the same type:
-
-```ts
-function length>(t: T): number {}
-
-function length(t: ArrayLike): number {}
-```
-
-In the first `length`, T is not necessary; notice that it's only
-referenced once, so it's not being used to constrain the type of the
-return value or other parameters.
-
-### Higher-kinded types
-
-TypeScript does not have higher kinded types, so the following is not legal:
-
-```ts
-function length, U>(m: T) {}
-```
-
-### Point-free programming
-
-Point-free programming — heavy use of currying and function
-composition — is possible in JavaScript, but can be verbose.
-In TypeScript, type inference often fails for point-free programs, so
-you'll end up specifying type parameters instead of value parameters. The
-result is so verbose that it's usually better to avoid point-free
-programming.
-
-## Module system
-
-JavaScript's modern module syntax is a bit like Haskell's, except that
-any file with `import` or `export` is implicitly a module:
-
-```ts
-import { value, Type } from "npm-package";
-import { other, Types } from "./local-package";
-import * as prefix from "../lib/third-package";
-```
-
-You can also import commonjs modules — modules written using node.js'
-module system:
-
-```ts
-import f = require("single-function-package");
-```
-
-You can export with an export list:
-
-```ts
-export { f };
-
-function f() {
-  return g();
-}
-function g() {} // g is not exported
-```
-
-Or by marking each export individually:
-
-```ts
-export function f { return g() }
-function g() { }
-```
-
-The latter style is more common but both are allowed, even in the same
-file.
-
-## `readonly` and `const`
-
-In JavaScript, mutability is the default, although it allows variable
-declarations with `const` to declare that the _reference_ is
-immutable. The referent is still mutable:
-
-```js
-const a = [1, 2, 3];
-a.push(102); // ):
-a[0] = 101; // D:
-```
-
-TypeScript additionally has a `readonly` modifier for properties.
-
-```ts
-interface Rx {
-  readonly x: number;
-}
-let rx: Rx = { x: 1 };
-rx.x = 12; // error
-```
-
-It also ships with a mapped type `Readonly` that makes
-all properties `readonly`:
-
-```ts
-interface X {
-  x: number;
-}
-let rx: Readonly = { x: 1 };
-rx.x = 12; // error
-```
-
-And it has a specific `ReadonlyArray` type that removes
-side-affecting methods and prevents writing to indices of the array,
-as well as special syntax for this type:
-
-```ts
-let a: ReadonlyArray = [1, 2, 3];
-let b: readonly number[] = [1, 2, 3];
-a.push(102); // error
-b[0] = 101; // error
-```
-
-You can also use a const-assertion, which operates on arrays and
-object literals:
-
-```ts
-let a = [1, 2, 3] as const;
-a.push(102); // error
-a[0] = 101; // error
-```
-
-However, none of these options are the default, so they are not
-consistently used in TypeScript code.
-
-## Next Steps
-
-This doc is a high level overview of the syntax and types you would use in everyday code. From here you should:
-
-- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m)
-- Explore the [Playground examples](/play#show-examples)
diff --git a/docs/documentation/zh/get-started/TS for JS Programmers.md b/docs/documentation/zh/get-started/TS for JS Programmers.md
deleted file mode 100644
index 1c70140f..00000000
--- a/docs/documentation/zh/get-started/TS for JS Programmers.md	
+++ /dev/null
@@ -1,289 +0,0 @@
----
-title: TypeScript for JavaScript Programmers
-short: TypeScript for JS Programmers
-layout: docs
-permalink: /docs/handbook/typescript-in-5-minutes.html
-oneline: Learn how TypeScript extends JavaScript
----
-
-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.
-
-For example, JavaScript provides language primitives like `string` and `number`, but it doesn't check that you've consistently assigned these. TypeScript does.
-
-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.
-
-This tutorial provides a brief overview of TypeScript, focusing on its type system.
-
-## 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.
-
-```ts twoslash
-let helloWorld = "Hello World";
-//  ^?
-```
-
-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.
-
-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.
-
-## 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.
-
-For example, to create an object with an inferred type which includes `name: string` and `id: number`, you can write:
-
-```ts twoslash
-const user = {
-  name: "Hayes",
-  id: 0,
-};
-```
-
-You can explicitly describe this object's shape using an `interface` declaration:
-
-```ts twoslash
-interface User {
-  name: string;
-  id: number;
-}
-```
-
-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:
-
-```ts twoslash
-interface User {
-  name: string;
-  id: number;
-}
-// ---cut---
-const user: User = {
-  name: "Hayes",
-  id: 0,
-};
-```
-
-If you provide an object that doesn't match the interface you have provided, TypeScript will warn you:
-
-```ts twoslash
-// @errors: 2322
-interface User {
-  name: string;
-  id: number;
-}
-
-const user: User = {
-  username: "Hayes",
-  id: 0,
-};
-```
-
-Since JavaScript supports classes and object-oriented programming, so does TypeScript. You can use an interface declaration with classes:
-
-```ts twoslash
-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);
-```
-
-You can use interfaces to annotate parameters and return values to functions:
-
-```ts twoslash
-// @noErrors
-interface User {
-  name: string;
-  id: number;
-}
-// ---cut---
-function getAdminUser(): User {
-  //...
-}
-
-function deleteUser(user: User) {
-  // ...
-}
-```
-
-There are already a small set of primitive types available in JavaScript: `boolean`, `bigint`, `null`, `number`, `string`, `symbol`, and `undefined`, which you can use in an interface. TypeScript extends this list with a few more, such as `any` (allow anything), [`unknown`](/play#example/unknown-and-never) (ensure someone using this type declares what the type is), [`never`](/play#example/unknown-and-never) (it's not possible that this type could happen), and `void` (a function which returns `undefined` or has no return value).
-
-You'll see that there are two syntaxes for building types: [Interfaces and Types](/play/?e=83#example/types-vs-interfaces). You should prefer `interface`. Use `type` when you need specific features.
-
-## 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.
-
-### 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`:
-
-```ts twoslash
-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.
-
-A popular use-case for union types is to describe the set of `string` or `number` [literals](/docs/handbook/literal-types.html) that a value is allowed to be:
-
-```ts twoslash
-type WindowStates = "open" | "closed" | "minimized";
-type LockStates = "locked" | "unlocked";
-type PositiveOddNumbersUnderTen = 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`:
-
-```ts twoslash
-function getLength(obj: string | string[]) {
-  return obj.length;
-}
-```
-
-To learn the type of a variable, use `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:
-
-
-```ts twoslash
-function wrapInArray(obj: string | string[]) {
-  if (typeof obj === "string") {
-    return [obj];
-//          ^?
-  }
-  return obj;
-}
-```
-
-### Generics
-
-Generics provide variables to types. 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.
-
-```ts
-type StringArray = Array;
-type NumberArray = Array;
-type ObjectWithNameArray = Array<{ name: string }>;
-```
-
-You can declare your own types that use generics:
-
-```ts twoslash
-// @errors: 2345
-interface Backpack {
-  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;
-
-// 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);
-```
-
-## 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".
-
-In a structural type system, if two objects have the same shape, they are considered to be of the same type.
-
-```ts twoslash
-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);
-```
-
-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.
-
-The shape-matching only requires a subset of the object's fields to match.
-
-```ts twoslash
-// @errors: 2345
-interface Point {
-  x: number;
-  y: number;
-}
-
-function logPoint(p: Point) {
-  console.log(`${p.x}, ${p.y}`);
-}
-// ---cut---
-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);
-```
-
-There is no difference between how classes and objects conform to shapes:
-
-```ts twoslash
-// @errors: 2345
-interface Point {
-  x: number;
-  y: number;
-}
-
-function logPoint(p: Point) {
-  console.log(`${p.x}, ${p.y}`);
-}
-// ---cut---
-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"
-```
-
-If the object or class has all the required properties, TypeScript will say they match, regardless of the implementation details.
-
-## Next Steps
-
-This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can:
-
-- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m)
-- Explore the [Playground examples](/play#show-examples)
diff --git a/docs/documentation/zh/get-started/TS for OOPers.md b/docs/documentation/zh/get-started/TS for OOPers.md
deleted file mode 100644
index 9e3891f3..00000000
--- a/docs/documentation/zh/get-started/TS for OOPers.md	
+++ /dev/null
@@ -1,194 +0,0 @@
----
-title: TypeScript for Java/C# Programmers
-short: TS for Java/C# Programmers
-layout: docs
-permalink: /docs/handbook/typescript-in-5-minutes-oop.html
-oneline: Learn TypeScript if you have a background in object-oriented languages
----
-
-TypeScript is a popular choice for programmers accustomed to other languages with static typing, such as C# and Java.
-
-TypeScript's type system offers many of the same benefits, such as better code completion, earlier detection of errors, and clearer communication between parts of your program.
-While TypeScript provides many familiar features for these developers, it's worth stepping back to see how JavaScript (and therefore TypeScript) differ from traditional OOP languages.
-Understanding these differences will help you write better JavaScript code, and avoid common pitfalls that programmers who go straight from C#/Java to TypeScript may fall in to.
-
-## Co-learning JavaScript
-
-If you're familiar with JavaScript already but are primarily a Java or C# programmer, this introductory page can help explain some of the common misconceptions and pitfalls you might be susceptible to.
-Some of the ways that TypeScript models types are quite different from Java or C#, and it's important to keep these in mind when learning TypeScript.
-
-If you're a Java or C# programmer that is new to JavaScript in general, we recommend learning a little bit of JavaScript _without_ types first to understand JavaScript's runtime behaviors.
-Because TypeScript doesn't change how your code _runs_, you'll still have to learn how JavaScript works in order to write code that actually does something!
-
-It's important to remember that TypeScript uses the same _runtime_ as JavaScript, so any resources about how to accomplish specific runtime behavior (converting a string to a number, displaying an alert, writing a file to disk, etc.) will always apply equally well to TypeScript programs.
-Don't limit yourself to TypeScript-specific resources!
-
-## Rethinking the Class
-
-C# and Java are what we might call _mandatory OOP_ languages.
-In these languages, the _class_ is the basic unit of code organization, and also the basic container of all data _and_ behavior at runtime.
-Forcing all functionality and data to be held in classes can be a good domain model for some problems, but not every domain _needs_ to be represented this way.
-
-### Free Functions and Data
-
-In JavaScript, functions can live anywhere, and data can be passed around freely without being inside a pre-defined `class` or `struct`.
-This flexibility is extremely powerful.
-"Free" functions (those not associated with a class) working over data without an implied OOP hierarchy tends to be the preferred model for writing programs in JavaScript.
-
-### Static Classes
-
-Additionally, certain constructs from C# and Java such as singletons and static classes are unnecessary in TypeScript.
-
-## OOP in TypeScript
-
-That said, you can still use classes if you like!
-Some problems are well-suited to being solved by a traditional OOP hierarchy, and TypeScript's support for JavaScript classes will make these models even more powerful.
-TypeScript supports many common patterns such as implementing interfaces, inheritance, and static methods.
-
-We'll cover classes later in this guide.
-
-## Rethinking Types
-
-TypeScript's understanding of a _type_ is actually quite different from C# or Java's.
-Let's explore some differences.
-
-### Nominal Reified Type Systems
-
-In C# or Java, any given value or object has one exact type - either `null`, a primitive, or a known class type.
-We can call methods like `value.GetType()` or `value.getClass()` to query the exact type at runtime.
-The definition of this type will reside in a class somewhere with some name, and we can't use two classes with similar shapes in lieu of each other unless there's an explicit inheritance relationship or commonly-implemented interface.
-
-These aspects describe a _reified, nominal_ type system.
-The types we wrote in the code are present at runtime, and the types are related via their declarations, not their structures.
-
-### Types as Sets
-
-In C# or Java, it's meaningful to think of a one-to-one correspondence between runtime types and their compile-time declarations.
-
-In TypeScript, it's better to think of a type as a _set of values_ that share something in common.
-Because types are just sets, a particular value can belong to _many_ sets at the same time.
-
-Once you start thinking of types as sets, certain operations become very natural.
-For example, in C#, it's awkward to pass around a value that is _either_ a `string` or `int`, because there isn't a single type that represents this sort of value.
-
-In TypeScript, this becomes very natural once you realize that every type is just a set.
-How do you describe a value that either belongs in the `string` set or the `number` set?
-It simply belongs to the _union_ of those sets: `string | number`.
-
-TypeScript provides a number of mechanisms to work with types in a set-theoretic way, and you'll find them more intuitive if you think of types as sets.
-
-### Erased Structural Types
-
-In TypeScript, objects are _not_ of a single exact type.
-For example, if we construct an object that satisfies an interface, we can use that object where that interface is expected even though there was no declarative relationship between the two.
-
-```ts twoslash
-interface Pointlike {
-  x: number;
-  y: number;
-}
-interface Named {
-  name: string;
-}
-
-function logPoint(point: Pointlike) {
-  console.log("x = " + point.x + ", y = " + point.y);
-}
-
-function logName(x: Named) {
-  console.log("Hello, " + x.name);
-}
-
-const obj = {
-  x: 0,
-  y: 0,
-  name: "Origin",
-};
-
-logPoint(obj);
-logName(obj);
-```
-
-TypeScript's type system is _structural_, not nominal: We can use `obj` as a `Pointlike` because it has `x` and `y` properties that are both numbers.
-The relationships between types are determined by the properties they contain, not whether they were declared with some particular relationship.
-
-TypeScript's type system is also _not reified_: There's nothing at runtime that will tell us that `obj` is `Pointlike`.
-In fact, the `Pointlike` type is not present _in any form_ at runtime.
-
-Going back to the idea of _types as sets_, we can think of `obj` as being a member of both the `Pointlike` set of values and the `Named` set of values.
-
-### Consequences of Structural Typing
-
-OOP programmers are often surprised by two particular aspects of structural typing.
-
-#### Empty Types
-
-The first is that the _empty type_ seems to defy expectation:
-
-```ts twoslash
-class Empty {}
-
-function fn(arg: Empty) {
-  // do something?
-}
-
-// No error, but this isn't an 'Empty' ?
-fn({ k: 10 });
-```
-
-TypeScript determines if the call to `fn` here is valid by seeing if the provided argument is a valid `Empty`.
-It does so by examining the _structure_ of `{ k: 10 }` and `class Empty { }`.
-We can see that `{ k: 10 }` has _all_ of the properties that `Empty` does, because `Empty` has no properties.
-Therefore, this is a valid call!
-
-This may seem surprising, but it's ultimately a very similar relationship to one enforced in nominal OOP languages.
-A subclass cannot _remove_ a property of its base class, because doing so would destroy the natural subtype relationship between the derived class and its base.
-Structural type systems simply identify this relationship implicitly by describing subtypes in terms of having properties of compatible types.
-
-#### Identical Types
-
-Another frequent source of surprise comes with identical types:
-
-```ts
-class Car {
-  drive() {
-    // hit the gas
-  }
-}
-class Golfer {
-  drive() {
-    // hit the ball far
-  }
-}
-
-// No error?
-let w: Car = new Golfer();
-```
-
-Again, this isn't an error because the _structures_ of these classes are the same.
-While this may seem like a potential source of confusion, in practice, identical classes that shouldn't be related are not common.
-
-We'll learn more about how classes relate to each other in the Classes chapter.
-
-### Reflection
-
-OOP programmers are accustomed to being able to query the type of any value, even a generic one:
-
-```csharp
-// C#
-static void LogType() {
-    Console.WriteLine(typeof(T).Name);
-}
-```
-
-Because TypeScript's type system is fully erased, information about e.g. the instantiation of a generic type parameter is not available at runtime.
-
-JavaScript does have some limited primitives like `typeof` and `instanceof`, but remember that these operators are still working on the values as they exist in the type-erased output code.
-For example, `typeof (new Car())` will be `"object"`, not `Car` or `"Car"`.
-
-## Next Steps
-
-This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can:
-
-- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m)
-- Explore the [Playground examples](/play#show-examples)
diff --git a/docs/documentation/zh/get-started/TS for the New Programmer.md b/docs/documentation/zh/get-started/TS for the New Programmer.md
deleted file mode 100644
index d000a6b3..00000000
--- a/docs/documentation/zh/get-started/TS for the New Programmer.md	
+++ /dev/null
@@ -1,194 +0,0 @@
----
-title: TypeScript for the New Programmer
-short: TS for the New Programmer
-layout: docs
-permalink: /docs/handbook/typescript-from-scratch.html
-oneline: Learn TypeScript from scratch
----
-
-Congratulations on choosing TypeScript as one of your first languages — you're already making good decisions!
-
-You've probably already heard that TypeScript is a "flavor" or "variant" of JavaScript.
-The relationship between TypeScript (TS) and JavaScript (JS) is rather unique among modern programming languages, so learning more about this relationship will help you understand how TypeScript adds to JavaScript.
-
-## What is JavaScript? A Brief History
-
-JavaScript (also known as ECMAScript) started its life as a simple scripting language for browsers.
-At the time it was invented, it was expected to be used for short snippets of code embedded in a web page — writing more than a few dozen lines of code would have been somewhat unusual.
-Due to this, early web browsers executed such code pretty slowly.
-Over time, though, JS became more and more popular, and web developers started using it to create interactive experiences.
-
-Web browser developers responded to this increased JS usage by optimizing their execution engines (dynamic compilation) and extending what could be done with it (adding APIs), which in turn made web developers use it even more.
-On modern websites, your browser is frequently running applications that span hundreds of thousands of lines of code.
-This is long and gradual growth of "the web", starting as a simple network of static pages, and evolving into a platform for rich _applications_ of all kinds.
-
-More than this, JS has become popular enough to be used outside the context of browsers, such as implementing JS servers using node.js.
-The "run anywhere" nature of JS makes it an attractive choice for cross-platform development.
-There are many developers these days that use _only_ JavaScript to program their entire stack!
-
-To summarize, we have a language that was designed for quick uses, and then grew to a full-fledged tool to write applications with millions of lines.
-Every language has its own _quirks_ — oddities and surprises, and JavaScript's humble beginning makes it have _many_ of these. Some examples:
-
-- JavaScript's equality operator (`==`) _coerces_ its arguments, leading to unexpected behavior:
-
-  ```js
-  if ("" == 0) {
-    // It is! But why??
-  }
-  if (1 < x < 3) {
-    // True for *any* value of x!
-  }
-  ```
-
-- JavaScript also allows accessing properties which aren't present:
-
-  ```js
-  const obj = { width: 10, height: 15 };
-  // Why is this NaN? Spelling is hard!
-  const area = obj.width * obj.heigth;
-  ```
-
-Most programming languages would throw an error when these sorts of errors occur, some would do so during compilation — before any code is running.
-When writing small programs, such quirks are annoying but manageable; when writing applications with hundreds or thousands of lines of code, these constant surprises are a serious problem.
-
-## TypeScript: A Static Type Checker
-
-We said earlier that some languages wouldn't allow those buggy programs to run at all.
-Detecting errors in code without running it is referred to as _static checking_.
-Determining what's an error and what's not based on the kinds of values being operated on is known as static _type_ checking.
-
-TypeScript checks a program for errors before execution, and does so based on the _kinds of values_, it's a _static type checker_.
-For example, the last example above has an error because of the _type_ of `obj`.
-Here's the error TypeScript found:
-
-```ts twoslash
-// @errors: 2551
-const obj = { width: 10, height: 15 };
-const area = obj.width * obj.heigth;
-```
-
-### A Typed Superset of JavaScript
-
-How does TypeScript relate to JavaScript, though?
-
-#### Syntax
-
-TypeScript is a language that is a _superset_ of JavaScript: JS syntax is therefore legal TS.
-Syntax refers to the way we write text to form a program.
-For example, this code has a _syntax_ error because it's missing a `)`:
-
-```ts twoslash
-// @errors: 1005
-let a = (4
-```
-
-TypeScript doesn't consider any JavaScript code to be an error because of its syntax.
-This means you can take any working JavaScript code and put it in a TypeScript file without worrying about exactly how it is written.
-
-#### Types
-
-However, TypeScript is a _typed_ superset, meaning that it adds rules about how different kinds of values can be used.
-The earlier error about `obj.heigth` was not a _syntax_ error: it is an error of using some kind of value (a _type_) in an incorrect way.
-
-As another example, this is JavaScript code that you can run in your browser, and it _will_ log a value:
-
-```js
-console.log(4 / []);
-```
-
-This syntactically-legal program logs `Infinity`.
-TypeScript, though, considers division of number by an array to be a nonsensical operation, and will issue an error:
-
-```ts twoslash
-// @errors: 2363
-console.log(4 / []);
-```
-
-It's possible you really _did_ intend to divide a number by an array, perhaps just to see what happens, but most of the time, though, this is a programming mistake.
-TypeScript's type checker is designed to allow correct programs through while still catching as many common errors as possible.
-(Later, we'll learn about settings you can use to configure how strictly TypeScript checks your code.)
-
-If you move some code from a JavaScript file to a TypeScript file, you might see _type errors_ depending on how the code is written.
-These may be legitimate problems with the code, or TypeScript being overly conservative.
-Throughout this guide we'll demonstrate how to add various TypeScript syntax to eliminate such errors.
-
-#### Runtime Behavior
-
-TypeScript is also a programming language that preserves the _runtime behavior_ of JavaScript.
-For example, dividing by zero in JavaScript produces `Infinity` instead of throwing a runtime exception.
-As a principle, TypeScript **never** changes the runtime behavior of JavaScript code.
-
-This means that if you move code from JavaScript to TypeScript, it is **guaranteed** to run the same way, even if TypeScript thinks that the code has type errors.
-
-Keeping the same runtime behavior as JavaScript is a foundational promise of TypeScript because it means you can easily transition between the two languages without worrying about subtle differences that might make your program stop working.
-
-
-
-#### Erased Types
-
-Roughly speaking, once TypeScript's compiler is done with checking your code, it _erases_ the types to produce the resulting "compiled" code.
-This means that once your code is compiled, the resulting plain JS code has no type information.
-
-This also means that TypeScript never changes the _behavior_ of your program based on the types it inferred.
-The bottom line is that while you might see type errors during compilation, the type system itself has no bearing on how your program works when it runs.
-
-Finally, TypeScript doesn't provide any additional runtime libraries.
-Your programs will use the same standard library (or external libraries) as JavaScript programs, so there's no additional TypeScript-specific framework to learn.
-
-
-
-## Learning JavaScript and TypeScript
-
-We frequently see the question "Should I learn JavaScript or TypeScript?".
-
-The answer is that you can't learn TypeScript without learning JavaScript!
-TypeScript shares syntax and runtime behavior with JavaScript, so anything you learn about JavaScript is helping you learn TypeScript at the same time.
-
-There are many, many resources available for programmers to learn JavaScript; you should _not_ ignore these resources if you're writing TypeScript.
-For example, there are about 20 times more StackOverflow questions tagged `javascript` than `typescript`, but _all_ of the `javascript` questions also apply to TypeScript.
-
-If you find yourself searching for something like "how to sort a list in TypeScript", remember: **TypeScript is JavaScript's runtime with a compile-time type checker**.
-The way you sort a list in TypeScript is the same way you do so in JavaScript.
-If you find a resource that uses TypeScript directly, that's great too, but don't limit yourself to thinking you need TypeScript-specific answers for everyday questions about how to accomplish runtime tasks.
-
-## Next Steps
-
-This was a brief overview of the syntax and tools used in everyday TypeScript. From here, you can:
-
-- Learn some of the JavaScript fundamentals, we recommend either:
-
-  - [Microsoft's JavaScript Resources](https://docs.microsoft.com/javascript/) or
-  - [JavaScript guide at the Mozilla Web Docs](https://developer.mozilla.org/docs/Web/JavaScript/Guide)
-
-- Continue to [TypeScript for JavaScript Programmers](/docs/handbook/typescript-in-5-minutes.html)
-- Read the full Handbook [from start to finish](/docs/handbook/intro.html) (30m)
-- Explore the [Playground examples](/play#show-examples)
-
-
-
diff --git a/docs/documentation/zh/handbook-v1/Basic Types.md b/docs/documentation/zh/handbook-v1/Basic Types.md
deleted file mode 100644
index 3ae3fb63..00000000
--- a/docs/documentation/zh/handbook-v1/Basic Types.md	
+++ /dev/null
@@ -1,417 +0,0 @@
----
-title: Basic Types
-layout: docs
-permalink: /docs/handbook/basic-types.html
-oneline: "Step two in learning TypeScript: The basic types."
-handbook: "true"
-deprecated_by: /docs/handbook/2/everyday-types.html
-# prettier-ignore
-deprecation_redirects: [
-  never, /docs/handbook/2/narrowing.html#the-never-type,
-  unknown, /docs/handbook/2/functions.html#unknown,
-  void, /docs/handbook/2/functions.html#void
-]
----
-
-For programs to be useful, we need to be able to work with some of the simplest units of data: numbers, strings, structures, boolean values, and the like.
-In TypeScript, we support the same types as you would expect in JavaScript, with an extra enumeration type thrown in to help things along.
-
-## Boolean
-
-The most basic datatype is the simple true/false value, which JavaScript and TypeScript call a `boolean` value.
-
-```ts  twoslash
-let isDone: boolean = false;
-```
-
-## Number
-
-As in JavaScript, all numbers in TypeScript are either floating point values or BigIntegers.
-These floating point numbers get the type `number`, while BigIntegers get the type `bigint`.
-In addition to hexadecimal and decimal literals, TypeScript also supports binary and octal literals introduced in ECMAScript 2015.
-
-```ts twoslash
-// @target: ES2020
-let decimal: number = 6;
-let hex: number = 0xf00d;
-let binary: number = 0b1010;
-let octal: number = 0o744;
-let big: bigint = 100n;
-```
-
-## String
-
-Another fundamental part of creating programs in JavaScript for webpages and servers alike is working with textual data.
-As in other languages, we use the type `string` to refer to these textual datatypes.
-Just like JavaScript, TypeScript also uses double quotes (`"`) or single quotes (`'`) to surround string data.
-
-```ts twoslash
-let color: string = "blue";
-// prettier-ignore
-color = 'red';
-```
-
-You can also use _template strings_, which can span multiple lines and have embedded expressions.
-These strings are surrounded by the backtick/backquote (`` ` ``) character, and embedded expressions are of the form `${ expr }`.
-
-```ts twoslash
-let fullName: string = `Bob Bobbington`;
-let age: number = 37;
-let sentence: string = `Hello, my name is ${fullName}.
-
-I'll be ${age + 1} years old next month.`;
-```
-
-This is equivalent to declaring `sentence` like so:
-
-```ts twoslash
-let fullName: string = `Bob Bobbington`;
-let age: number = 37;
-// ---cut---
-let sentence: string =
-  "Hello, my name is " +
-  fullName +
-  ".\n\n" +
-  "I'll be " +
-  (age + 1) +
-  " years old next month.";
-```
-
-## Array
-
-TypeScript, like JavaScript, allows you to work with arrays of values.
-Array types can be written in one of two ways.
-In the first, you use the type of the elements followed by `[]` to denote an array of that element type:
-
-```ts twoslash
-let list: number[] = [1, 2, 3];
-```
-
-The second way uses a generic array type, `Array`:
-
-```ts twoslash
-let list: Array = [1, 2, 3];
-```
-
-## Tuple
-
-Tuple types allow you to express an array with a fixed number of elements whose types are known, but need not be the same. For example, you may want to represent a value as a pair of a `string` and a `number`:
-
-```ts twoslash
-// @errors: 2322
-// Declare a tuple type
-let x: [string, number];
-// Initialize it
-x = ["hello", 10]; // OK
-// Initialize it incorrectly
-x = [10, "hello"]; // Error
-```
-
-When accessing an element with a known index, the correct type is retrieved:
-
-```ts twoslash
-// @errors: 2339
-let x: [string, number];
-x = ["hello", 10]; // OK
-/// ---cut---
-// OK
-console.log(x[0].substring(1));
-
-console.log(x[1].substring(1));
-```
-
-Accessing an element outside the set of known indices fails with an error:
-
-```ts twoslash
-// @errors: 2493 2532 2322
-let x: [string, number];
-x = ["hello", 10]; // OK
-/// ---cut---
-x[3] = "world";
-
-console.log(x[5].toString());
-```
-
-## Enum
-
-A helpful addition to the standard set of datatypes from JavaScript is the `enum`.
-As in languages like C#, an enum is a way of giving more friendly names to sets of numeric values.
-
-```ts twoslash
-enum Color {
-  Red,
-  Green,
-  Blue,
-}
-let c: Color = Color.Green;
-```
-
-By default, enums begin numbering their members starting at `0`.
-You can change this by manually setting the value of one of its members.
-For example, we can start the previous example at `1` instead of `0`:
-
-```ts twoslash
-enum Color {
-  Red = 1,
-  Green,
-  Blue,
-}
-let c: Color = Color.Green;
-```
-
-Or, even manually set all the values in the enum:
-
-```ts twoslash
-enum Color {
-  Red = 1,
-  Green = 2,
-  Blue = 4,
-}
-let c: Color = Color.Green;
-```
-
-A handy feature of enums is that you can also go from a numeric value to the name of that value in the enum.
-For example, if we had the value `2` but weren't sure what that mapped to in the `Color` enum above, we could look up the corresponding name:
-
-```ts twoslash
-enum Color {
-  Red = 1,
-  Green,
-  Blue,
-}
-let colorName: string = Color[2];
-
-// Displays 'Green'
-console.log(colorName);
-```
-
-## Unknown
-
-We may need to describe the type of variables that we do not know when we are writing an application.
-These values may come from dynamic content – e.g. from the user – or we may want to intentionally accept all values in our API.
-In these cases, we want to provide a type that tells the compiler and future readers that this variable could be anything, so we give it the `unknown` type.
-
-```ts twoslash
-let notSure: unknown = 4;
-notSure = "maybe a string instead";
-
-// OK, definitely a boolean
-notSure = false;
-```
-
-If you have a variable with an unknown type, you can narrow it to something more specific by doing `typeof` checks, comparison checks, or more advanced type guards that will be discussed in a later chapter:
-
-```ts twoslash
-// @errors: 2322 2322 2322
-declare const maybe: unknown;
-// 'maybe' could be a string, object, boolean, undefined, or other types
-const aNumber: number = maybe;
-
-if (maybe === true) {
-  // TypeScript knows that maybe is a boolean now
-  const aBoolean: boolean = maybe;
-  // So, it cannot be a string
-  const aString: string = maybe;
-}
-
-if (typeof maybe === "string") {
-  // TypeScript knows that maybe is a string
-  const aString: string = maybe;
-  // So, it cannot be a boolean
-  const aBoolean: boolean = maybe;
-}
-```
-
-## Any
-
-In some situations, not all type information is available or its declaration would take an inappropriate amount of effort.
-These may occur for values from code that has been written without TypeScript or a 3rd party library.
-In these cases, we might want to opt-out of type checking.
-To do so, we label these values with the `any` type:
-
-```ts twoslash
-declare function getValue(key: string): any;
-// OK, return value of 'getValue' is not checked
-const str: string = getValue("myString");
-```
-
-The `any` type is a powerful way to work with existing JavaScript, allowing you to gradually opt-in and opt-out of type checking during compilation.
-
-Unlike `unknown`, variables of type `any` allow you to access arbitrary properties, even ones that don't exist.
-These properties include functions and TypeScript will not check their existence or type:
-
-```ts twoslash
-// @errors: 2571
-let looselyTyped: any = 4;
-// OK, ifItExists might exist at runtime
-looselyTyped.ifItExists();
-// OK, toFixed exists (but the compiler doesn't check)
-looselyTyped.toFixed();
-
-let strictlyTyped: unknown = 4;
-strictlyTyped.toFixed();
-```
-
-The `any` will continue to propagate through your objects:
-
-```ts twoslash
-let looselyTyped: any = {};
-let d = looselyTyped.a.b.c.d;
-//  ^?
-```
-
-After all, remember that all the convenience of `any` comes at the cost of losing type safety.
-Type safety is one of the main motivations for using TypeScript and you should try to avoid using `any` when not necessary.
-
-## Void
-
-`void` is a little like the opposite of `any`: the absence of having any type at all.
-You may commonly see this as the return type of functions that do not return a value:
-
-```ts twoslash
-function warnUser(): void {
-  console.log("This is my warning message");
-}
-```
-
-Declaring variables of type `void` is not useful because you can only assign `null` (only if `--strictNullChecks` is not specified, see next section) or `undefined` to them:
-
-```ts twoslash
-// @strict: false
-let unusable: void = undefined;
-// OK if `--strictNullChecks` is not given
-unusable = null;
-```
-
-## Null and Undefined
-
-In TypeScript, both `undefined` and `null` actually have their types named `undefined` and `null` respectively.
-Much like `void`, they're not extremely useful on their own:
-
-```ts twoslash
-// Not much else we can assign to these variables!
-let u: undefined = undefined;
-let n: null = null;
-```
-
-By default `null` and `undefined` are subtypes of all other types.
-That means you can assign `null` and `undefined` to something like `number`.
-
-However, when using the `--strictNullChecks` flag, `null` and `undefined` are only assignable to `unknown`, `any` and their respective types (the one exception being that `undefined` is also assignable to `void`).
-This helps avoid _many_ common errors.
-In cases where you want to pass in either a `string` or `null` or `undefined`, you can use the union type `string | null | undefined`.
-
-Union types are an advanced topic that we'll cover in a later chapter.
-
-> As a note: we encourage the use of `--strictNullChecks` when possible, but for the purposes of this handbook, we will assume it is turned off.
-
-## Never
-
-The `never` type represents the type of values that never occur.
-For instance, `never` is the return type for a function expression or an arrow function expression that always throws an exception or one that never returns.
-Variables also acquire the type `never` when narrowed by any type guards that can never be true.
-
-The `never` type is a subtype of, and assignable to, every type; however, _no_ type is a subtype of, or assignable to, `never` (except `never` itself).
-Even `any` isn't assignable to `never`.
-
-Some examples of functions returning `never`:
-
-```ts twoslash
-// Function returning never must not have a reachable end point
-function error(message: string): never {
-  throw new Error(message);
-}
-
-// Inferred return type is never
-function fail() {
-  return error("Something failed");
-}
-
-// Function returning never must not have a reachable end point
-function infiniteLoop(): never {
-  while (true) {}
-}
-```
-
-## Object
-
-`object` is a type that represents the non-primitive type, i.e. anything that is not `number`, `string`, `boolean`, `bigint`, `symbol`, `null`, or `undefined`.
-
-With `object` type, APIs like `Object.create` can be better represented. For example:
-
-```ts twoslash
-// @errors: 2345
-declare function create(o: object | null): void;
-
-// OK
-create({ prop: 0 });
-create(null);
-create(undefined); // with `--strictNullChecks` flag enabled, undefined is not a subtype of null
-
-create(42);
-create("string");
-create(false);
-```
-
-Generally, you won't need to use this.
-
-## Type assertions
-
-Sometimes you'll end up in a situation where you'll know more about a value than TypeScript does.
-Usually, this will happen when you know the type of some entity could be more specific than its current type.
-
-_Type assertions_ are a way to tell the compiler "trust me, I know what I'm doing."
-A type assertion is like a type cast in other languages, but it performs no special checking or restructuring of data.
-It has no runtime impact and is used purely by the compiler.
-TypeScript assumes that you, the programmer, have performed any special checks that you need.
-
-Type assertions have two forms.
-
-One is the `as`-syntax:
-
-```ts twoslash
-let someValue: unknown = "this is a string";
-
-let strLength: number = (someValue as string).length;
-```
-
-The other version is the "angle-bracket" syntax:
-
-```ts twoslash
-let someValue: unknown = "this is a string";
-
-let strLength: number = (someValue).length;
-```
-
-The two samples are equivalent.
-Using one over the other is mostly a choice of preference; however, when using TypeScript with JSX, only `as`-style assertions are allowed.
-
-## A note about `let`
-
-You may have noticed that so far, we've been using the `let` keyword instead of JavaScript's `var` keyword which you might be more familiar with.
-The `let` keyword is actually a newer JavaScript construct that TypeScript makes available.
-You can read in the Handbook Reference on [Variable Declarations](/docs/handbook/variable-declarations.html) more about how `let` and `const` fix a lot of the problems with `var`.
-
-## About `Number`, `String`, `Boolean`, `Symbol` and `Object`
-
-It can be tempting to think that the types `Number`, `String`, `Boolean`, `Symbol`, or `Object` are the same as the lowercase versions recommended above.
-These types do not refer to the language primitives however, and almost never should be used as a type.
-
-```ts twoslash
-// @errors: 2339
-function reverse(s: String): String {
-  return s.split("").reverse().join("");
-}
-
-reverse("hello world");
-```
-
-Instead, use the types `number`, `string`, `boolean`, `object` and `symbol`.
-
-```ts twoslash
-function reverse(s: string): string {
-  return s.split("").reverse().join("");
-}
-
-reverse("hello world");
-```
diff --git a/docs/documentation/zh/handbook-v1/Classes.md b/docs/documentation/zh/handbook-v1/Classes.md
deleted file mode 100644
index f0e368c9..00000000
--- a/docs/documentation/zh/handbook-v1/Classes.md
+++ /dev/null
@@ -1,611 +0,0 @@
----
-title: Classes
-layout: docs
-permalink: /docs/handbook/classes.html
-oneline: How classes work in TypeScript
-handbook: "true"
-deprecated_by: /docs/handbook/2/classes.html
----
-
-Traditional JavaScript uses functions and prototype-based inheritance to build up reusable components, but this may feel a bit awkward to programmers more comfortable with an object-oriented approach, where classes inherit functionality and objects are built from these classes.
-Starting with ECMAScript 2015, also known as ECMAScript 6, JavaScript programmers can build their applications using this object-oriented class-based approach.
-In TypeScript, we allow developers to use these techniques now, and compile them down to JavaScript that works across all major browsers and platforms, without having to wait for the next version of JavaScript.
-
-## Classes
-
-Let's take a look at a simple class-based example:
-
-```ts twoslash
-class Greeter {
-  greeting: string;
-
-  constructor(message: string) {
-    this.greeting = message;
-  }
-
-  greet() {
-    return "Hello, " + this.greeting;
-  }
-}
-
-let greeter = new Greeter("world");
-```
-
-The syntax should look familiar if you've used C# or Java before.
-We declare a new class `Greeter`. This class has three members: a property called `greeting`, a constructor, and a method `greet`.
-
-You'll notice that in the class when we refer to one of the members of the class we prepend `this.`.
-This denotes that it's a member access.
-
-In the last line we construct an instance of the `Greeter` class using `new`.
-This calls into the constructor we defined earlier, creating a new object with the `Greeter` shape, and running the constructor to initialize it.
-
-## Inheritance
-
-In TypeScript, we can use common object-oriented patterns.
-One of the most fundamental patterns in class-based programming is being able to extend existing classes to create new ones using inheritance.
-
-Let's take a look at an example:
-
-```ts twoslash
-class Animal {
-  move(distanceInMeters: number = 0) {
-    console.log(`Animal moved ${distanceInMeters}m.`);
-  }
-}
-
-class Dog extends Animal {
-  bark() {
-    console.log("Woof! Woof!");
-  }
-}
-
-const dog = new Dog();
-dog.bark();
-dog.move(10);
-dog.bark();
-```
-
-This example shows the most basic inheritance feature: classes inherit properties and methods from base classes.
-Here, `Dog` is a _derived_ class that derives from the `Animal` _base_ class using the `extends` keyword.
-Derived classes are often called _subclasses_, and base classes are often called _superclasses_.
-
-Because `Dog` extends the functionality from `Animal`, we were able to create an instance of `Dog` that could both `bark()` and `move()`.
-
-Let's now look at a more complex example.
-
-```ts twoslash
-class Animal {
-  name: string;
-  constructor(theName: string) {
-    this.name = theName;
-  }
-  move(distanceInMeters: number = 0) {
-    console.log(`${this.name} moved ${distanceInMeters}m.`);
-  }
-}
-
-class Snake extends Animal {
-  constructor(name: string) {
-    super(name);
-  }
-  move(distanceInMeters = 5) {
-    console.log("Slithering...");
-    super.move(distanceInMeters);
-  }
-}
-
-class Horse extends Animal {
-  constructor(name: string) {
-    super(name);
-  }
-  move(distanceInMeters = 45) {
-    console.log("Galloping...");
-    super.move(distanceInMeters);
-  }
-}
-
-let sam = new Snake("Sammy the Python");
-let tom: Animal = new Horse("Tommy the Palomino");
-
-sam.move();
-tom.move(34);
-```
-
-This example covers a few other features we didn't previously mention.
-Again, we see the `extends` keywords used to create two new subclasses of `Animal`: `Horse` and `Snake`.
-
-One difference from the prior example is that each derived class that contains a constructor function _must_ call `super()` which will execute the constructor of the base class.
-What's more, before we _ever_ access a property on `this` in a constructor body, we _have_ to call `super()`.
-This is an important rule that TypeScript will enforce.
-
-The example also shows how to override methods in the base class with methods that are specialized for the subclass.
-Here both `Snake` and `Horse` create a `move` method that overrides the `move` from `Animal`, giving it functionality specific to each class.
-Note that even though `tom` is declared as an `Animal`, since its value is a `Horse`, calling `tom.move(34)` will call the overriding method in `Horse`:
-
-```
-Slithering...
-Sammy the Python moved 5m.
-Galloping...
-Tommy the Palomino moved 34m.
-```
-
-## Public, private, and protected modifiers
-
-## Public by default
-
-In our examples, we've been able to freely access the members that we declared throughout our programs.
-If you're familiar with classes in other languages, you may have noticed in the above examples we haven't had to use the word `public` to accomplish this; for instance, C# requires that each member be explicitly labeled `public` to be visible.
-In TypeScript, each member is `public` by default.
-
-You may still mark a member `public` explicitly.
-We could have written the `Animal` class from the previous section in the following way:
-
-```ts twoslash
-class Animal {
-  public name: string;
-
-  public constructor(theName: string) {
-    this.name = theName;
-  }
-
-  public move(distanceInMeters: number) {
-    console.log(`${this.name} moved ${distanceInMeters}m.`);
-  }
-}
-```
-
-## ECMAScript Private Fields
-
-With TypeScript 3.8, TypeScript supports the new JavaScript syntax for private fields:
-
-```ts twoslash
-// @errors: 18013
-class Animal {
-  #name: string;
-  constructor(theName: string) {
-    this.#name = theName;
-  }
-}
-
-new Animal("Cat").#name;
-```
-
-This syntax is built into the JavaScript runtime and can have better guarantees about the isolation of each private field.
-Right now, the best documentation for these private fields is in the TypeScript 3.8 [release notes](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields).
-
-## Understanding TypeScript's `private`
-
-TypeScript also has its own way to declare a member as being marked `private`, it cannot be accessed from outside of its containing class. For example:
-
-```ts twoslash
-// @errors: 2341
-class Animal {
-  private name: string;
-
-  constructor(theName: string) {
-    this.name = theName;
-  }
-}
-
-new Animal("Cat").name;
-```
-
-TypeScript is a structural type system.
-When we compare two different types, regardless of where they came from, if the types of all members are compatible, then we say the types themselves are compatible.
-
-However, when comparing types that have `private` and `protected` members, we treat these types differently.
-For two types to be considered compatible, if one of them has a `private` member, then the other must have a `private` member that originated in the same declaration.
-The same applies to `protected` members.
-
-Let's look at an example to better see how this plays out in practice:
-
-```ts twoslash
-// @errors: 2322
-class Animal {
-  private name: string;
-  constructor(theName: string) {
-    this.name = theName;
-  }
-}
-
-class Rhino extends Animal {
-  constructor() {
-    super("Rhino");
-  }
-}
-
-class Employee {
-  private name: string;
-  constructor(theName: string) {
-    this.name = theName;
-  }
-}
-
-let animal = new Animal("Goat");
-let rhino = new Rhino();
-let employee = new Employee("Bob");
-
-animal = rhino;
-animal = employee;
-```
-
-In this example, we have an `Animal` and a `Rhino`, with `Rhino` being a subclass of `Animal`.
-We also have a new class `Employee` that looks identical to `Animal` in terms of shape.
-We create some instances of these classes and then try to assign them to each other to see what will happen.
-Because `Animal` and `Rhino` share the `private` side of their shape from the same declaration of `private name: string` in `Animal`, they are compatible. However, this is not the case for `Employee`.
-When we try to assign from an `Employee` to `Animal` we get an error that these types are not compatible.
-Even though `Employee` also has a `private` member called `name`, it's not the one we declared in `Animal`.
-
-## Understanding `protected`
-
-The `protected` modifier acts much like the `private` modifier with the exception that members declared `protected` can also be accessed within deriving classes. For example,
-
-```ts twoslash
-// @errors: 2445
-class Person {
-  protected name: string;
-  constructor(name: string) {
-    this.name = name;
-  }
-}
-
-class Employee extends Person {
-  private department: string;
-
-  constructor(name: string, department: string) {
-    super(name);
-    this.department = department;
-  }
-
-  public getElevatorPitch() {
-    return `Hello, my name is ${this.name} and I work in ${this.department}.`;
-  }
-}
-
-let howard = new Employee("Howard", "Sales");
-console.log(howard.getElevatorPitch());
-console.log(howard.name);
-```
-
-Notice that while we can't use `name` from outside of `Person`, we can still use it from within an instance method of `Employee` because `Employee` derives from `Person`.
-
-A constructor may also be marked `protected`.
-This means that the class cannot be instantiated outside of its containing class, but can be extended. For example,
-
-```ts twoslash
-// @errors: 2674
-class Person {
-  protected name: string;
-  protected constructor(theName: string) {
-    this.name = theName;
-  }
-}
-
-// Employee can extend Person
-class Employee extends Person {
-  private department: string;
-
-  constructor(name: string, department: string) {
-    super(name);
-    this.department = department;
-  }
-
-  public getElevatorPitch() {
-    return `Hello, my name is ${this.name} and I work in ${this.department}.`;
-  }
-}
-
-let howard = new Employee("Howard", "Sales");
-let john = new Person("John");
-```
-
-## Readonly modifier
-
-You can make properties readonly by using the `readonly` keyword.
-Readonly properties must be initialized at their declaration or in the constructor.
-
-```ts twoslash
-// @errors: 2540
-class Octopus {
-  readonly name: string;
-  readonly numberOfLegs: number = 8;
-
-  constructor(theName: string) {
-    this.name = theName;
-  }
-}
-
-let dad = new Octopus("Man with the 8 strong legs");
-dad.name = "Man with the 3-piece suit";
-```
-
-## Parameter properties
-
-In our last example, we had to declare a readonly member `name` and a constructor parameter `theName` in the `Octopus` class. This is needed in order to have the value of `theName` accessible after the `Octopus` constructor is executed.
-_Parameter properties_ let you create and initialize a member in one place.
-Here's a further revision of the previous `Octopus` class using a parameter property:
-
-```ts twoslash
-class Octopus {
-  readonly numberOfLegs: number = 8;
-  constructor(readonly name: string) {}
-}
-
-let dad = new Octopus("Man with the 8 strong legs");
-dad.name;
-```
-
-Notice how we dropped `theName` altogether and just use the shortened `readonly name: string` parameter on the constructor to create and initialize the `name` member.
-We've consolidated the declarations and assignment into one location.
-
-Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or `readonly`, or both.
-Using `private` for a parameter property declares and initializes a private member; likewise, the same is done for `public`, `protected`, and `readonly`.
-
-## Accessors
-
-TypeScript supports getters/setters as a way of intercepting accesses to a member of an object.
-This gives you a way of having finer-grained control over how a member is accessed on each object.
-
-Let's convert a simple class to use `get` and `set`.
-First, let's start with an example without getters and setters.
-
-```ts twoslash
-// @strict: false
-class Employee {
-  fullName: string;
-}
-
-let employee = new Employee();
-employee.fullName = "Bob Smith";
-
-if (employee.fullName) {
-  console.log(employee.fullName);
-}
-```
-
-While allowing people to randomly set `fullName` directly is pretty handy, we may also want enforce some constraints when `fullName` is set.
-
-In this version, we add a setter that checks the length of the `newName` to make sure it's compatible with the max-length of our backing database field. If it isn't we throw an error notifying client code that something went wrong.
-
-To preserve existing functionality, we also add a simple getter that retrieves `fullName` unmodified.
-
-```ts twoslash
-// @strict: false
-const fullNameMaxLength = 10;
-
-class Employee {
-  private _fullName: string = "";
-
-  get fullName(): string {
-    return this._fullName;
-  }
-
-  set fullName(newName: string) {
-    if (newName && newName.length > fullNameMaxLength) {
-      throw new Error("fullName has a max length of " + fullNameMaxLength);
-    }
-
-    this._fullName = newName;
-  }
-}
-
-let employee = new Employee();
-employee.fullName = "Bob Smith";
-
-if (employee.fullName) {
-  console.log(employee.fullName);
-}
-```
-
-To prove to ourselves that our accessor is now checking the length of values, we can attempt to assign a name longer than 10 characters and verify that we get an error.
-
-A couple of things to note about accessors:
-
-First, accessors require you to set the compiler to output ECMAScript 5 or higher.
-Downleveling to ECMAScript 3 is not supported.
-Second, accessors with a `get` and no `set` are automatically inferred to be `readonly`.
-This is helpful when generating a `.d.ts` file from your code, because users of your property can see that they can't change it.
-
-## Static Properties
-
-Up to this point, we've only talked about the _instance_ members of the class, those that show up on the object when it's instantiated.
-We can also create _static_ members of a class, those that are visible on the class itself rather than on the instances.
-In this example, we use `static` on the origin, as it's a general value for all grids.
-Each instance accesses this value through prepending the name of the class.
-Similarly to prepending `this.` in front of instance accesses, here we prepend `Grid.` in front of static accesses.
-
-```ts twoslash
-class Grid {
-  static origin = { x: 0, y: 0 };
-
-  calculateDistanceFromOrigin(point: { x: number; y: number }) {
-    let xDist = point.x - Grid.origin.x;
-    let yDist = point.y - Grid.origin.y;
-    return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
-  }
-
-  constructor(public scale: number) {}
-}
-
-let grid1 = new Grid(1.0); // 1x scale
-let grid2 = new Grid(5.0); // 5x scale
-
-console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 }));
-console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 }));
-```
-
-## Abstract Classes
-
-Abstract classes are base classes from which other classes may be derived.
-They may not be instantiated directly.
-Unlike an interface, an abstract class may contain implementation details for its members.
-The `abstract` keyword is used to define abstract classes as well as abstract methods within an abstract class.
-
-```ts twoslash
-abstract class Animal {
-  abstract makeSound(): void;
-
-  move(): void {
-    console.log("roaming the earth...");
-  }
-}
-```
-
-Methods within an abstract class that are marked as abstract do not contain an implementation and must be implemented in derived classes.
-Abstract methods share a similar syntax to interface methods.
-Both define the signature of a method without including a method body.
-However, abstract methods must include the `abstract` keyword and may optionally include access modifiers.
-
-```ts twoslash
-// @errors: 2511 2339
-abstract class Department {
-  constructor(public name: string) {}
-
-  printName(): void {
-    console.log("Department name: " + this.name);
-  }
-
-  abstract printMeeting(): void; // must be implemented in derived classes
-}
-
-class AccountingDepartment extends Department {
-  constructor() {
-    super("Accounting and Auditing"); // constructors in derived classes must call super()
-  }
-
-  printMeeting(): void {
-    console.log("The Accounting Department meets each Monday at 10am.");
-  }
-
-  generateReports(): void {
-    console.log("Generating accounting reports...");
-  }
-}
-
-let department: Department; // ok to create a reference to an abstract type
-department = new Department(); // error: cannot create an instance of an abstract class
-department = new AccountingDepartment(); // ok to create and assign a non-abstract subclass
-department.printName();
-department.printMeeting();
-department.generateReports(); // error: department is not of type AccountingDepartment, cannot access generateReports
-```
-
-## Advanced Techniques
-
-## Constructor functions
-
-When you declare a class in TypeScript, you are actually creating multiple declarations at the same time.
-The first is the type of the _instance_ of the class.
-
-```ts twoslash
-class Greeter {
-  greeting: string;
-
-  constructor(message: string) {
-    this.greeting = message;
-  }
-
-  greet() {
-    return "Hello, " + this.greeting;
-  }
-}
-
-let greeter: Greeter;
-greeter = new Greeter("world");
-console.log(greeter.greet()); // "Hello, world"
-```
-
-Here, when we say `let greeter: Greeter`, we're using `Greeter` as the type of instances of the class `Greeter`.
-This is almost second nature to programmers from other object-oriented languages.
-
-We're also creating another value that we call the _constructor function_.
-This is the function that is called when we `new` up instances of the class.
-To see what this looks like in practice, let's take a look at the JavaScript created by the above example:
-
-```ts twoslash
-// @strict: false
-let Greeter = (function () {
-  function Greeter(message) {
-    this.greeting = message;
-  }
-
-  Greeter.prototype.greet = function () {
-    return "Hello, " + this.greeting;
-  };
-
-  return Greeter;
-})();
-
-let greeter;
-greeter = new Greeter("world");
-console.log(greeter.greet()); // "Hello, world"
-```
-
-Here, `let Greeter` is going to be assigned the constructor function.
-When we call `new` and run this function, we get an instance of the class.
-The constructor function also contains all of the static members of the class.
-Another way to think of each class is that there is an _instance_ side and a _static_ side.
-
-Let's modify the example a bit to show this difference:
-
-```ts twoslash
-// @strict: false
-class Greeter {
-  static standardGreeting = "Hello, there";
-  greeting: string;
-  greet() {
-    if (this.greeting) {
-      return "Hello, " + this.greeting;
-    } else {
-      return Greeter.standardGreeting;
-    }
-  }
-}
-
-let greeter1: Greeter;
-greeter1 = new Greeter();
-console.log(greeter1.greet()); // "Hello, there"
-
-let greeterMaker: typeof Greeter = Greeter;
-greeterMaker.standardGreeting = "Hey there!";
-
-let greeter2: Greeter = new greeterMaker();
-console.log(greeter2.greet()); // "Hey there!"
-
-let greeter3: Greeter;
-greeter3 = new Greeter();
-console.log(greeter3.greet()); // "Hey there!"
-```
-
-In this example, `greeter1` works similarly to before.
-We instantiate the `Greeter` class, and use this object.
-This we have seen before.
-
-Next, we then use the class directly.
-Here we create a new variable called `greeterMaker`.
-This variable will hold the class itself, or said another way its constructor function.
-Here we use `typeof Greeter`, that is "give me the type of the `Greeter` class itself" rather than the instance type.
-Or, more precisely, "give me the type of the symbol called `Greeter`," which is the type of the constructor function.
-This type will contain all of the static members of Greeter along with the constructor that creates instances of the `Greeter` class.
-We show this by using `new` on `greeterMaker`, creating new instances of `Greeter` and invoking them as before.
-It is also good to mention that changing static property is frowned upon, here `greeter3` has `"Hey there!"` instead of `"Hello, there"` on `standardGreeting`.
-
-## Using a class as an interface
-
-As we said in the previous section, a class declaration creates two things: a type representing instances of the class and a constructor function.
-Because classes create types, you can use them in the same places you would be able to use interfaces.
-
-```ts twoslash
-// @strict: false
-class Point {
-  x: number;
-  y: number;
-}
-
-interface Point3d extends Point {
-  z: number;
-}
-
-let point3d: Point3d = { x: 1, y: 2, z: 3 };
-```
diff --git a/docs/documentation/zh/handbook-v1/Functions.md b/docs/documentation/zh/handbook-v1/Functions.md
deleted file mode 100644
index ffbed924..00000000
--- a/docs/documentation/zh/handbook-v1/Functions.md
+++ /dev/null
@@ -1,546 +0,0 @@
----
-title: Functions
-layout: docs
-permalink: /docs/handbook/functions.html
-oneline: How to add types to a function
-handbook: "true"
-deprecated_by: /docs/handbook/2/functions.html
----
-
-Functions are the fundamental building block of any application in JavaScript.
-They're how you build up layers of abstraction, mimicking classes, information hiding, and modules.
-In TypeScript, while there are classes, namespaces, and modules, functions still play the key role in describing how to _do_ things.
-TypeScript also adds some new capabilities to the standard JavaScript functions to make them easier to work with.
-
-## Functions
-
-To begin, just as in JavaScript, TypeScript functions can be created both as a named function or as an anonymous function.
-This allows you to choose the most appropriate approach for your application, whether you're building a list of functions in an API or a one-off function to hand off to another function.
-
-To quickly recap what these two approaches look like in JavaScript:
-
-```ts twoslash
-// @strict: false
-// Named function
-function add(x, y) {
-  return x + y;
-}
-
-// Anonymous function
-let myAdd = function (x, y) {
-  return x + y;
-};
-```
-
-Just as in JavaScript, functions can refer to variables outside of the function body.
-When they do so, they're said to _capture_ these variables.
-While understanding how this works (and the trade-offs when using this technique) is outside of the scope of this article, having a firm understanding how this mechanic works is an important piece of working with JavaScript and TypeScript.
-
-```ts twoslash
-// @strict: false
-let z = 100;
-
-function addToZ(x, y) {
-  return x + y + z;
-}
-```
-
-## Function Types
-
-## Typing the function
-
-Let's add types to our simple examples from earlier:
-
-```ts twoslash
-function add(x: number, y: number): number {
-  return x + y;
-}
-
-let myAdd = function (x: number, y: number): number {
-  return x + y;
-};
-```
-
-We can add types to each of the parameters and then to the function itself to add a return type.
-TypeScript can figure the return type out by looking at the return statements, so we can also optionally leave this off in many cases.
-
-## Writing the function type
-
-Now that we've typed the function, let's write the full type of the function out by looking at each piece of the function type.
-
-```ts twoslash
-let myAdd: (x: number, y: number) => number = function (
-  x: number,
-  y: number
-): number {
-  return x + y;
-};
-```
-
-A function's type has the same two parts: the type of the arguments and the return type.
-When writing out the whole function type, both parts are required.
-We write out the parameter types just like a parameter list, giving each parameter a name and a type.
-This name is just to help with readability.
-We could have instead written:
-
-```ts twoslash
-let myAdd: (baseValue: number, increment: number) => number = function (
-  x: number,
-  y: number
-): number {
-  return x + y;
-};
-```
-
-As long as the parameter types line up, it's considered a valid type for the function, regardless of the names you give the parameters in the function type.
-
-The second part is the return type.
-We make it clear which is the return type by using an arrow (`=>`) between the parameters and the return type.
-As mentioned before, this is a required part of the function type, so if the function doesn't return a value, you would use `void` instead of leaving it off.
-
-Of note, only the parameters and the return type make up the function type.
-Captured variables are not reflected in the type.
-In effect, captured variables are part of the "hidden state" of any function and do not make up its API.
-
-## Inferring the types
-
-In playing with the example, you may notice that the TypeScript compiler can figure out the type even if you only have types on one side of the equation:
-
-```ts twoslash
-// The parameters 'x' and 'y' have the type number
-let myAdd = function (x: number, y: number): number {
-  return x + y;
-};
-
-// myAdd has the full function type
-let myAdd2: (baseValue: number, increment: number) => number = function (x, y) {
-  return x + y;
-};
-```
-
-This is called "contextual typing", a form of type inference.
-This helps cut down on the amount of effort to keep your program typed.
-
-## Optional and Default Parameters
-
-In TypeScript, every parameter is assumed to be required by the function.
-This doesn't mean that it can't be given `null` or `undefined`, but rather, when the function is called, the compiler will check that the user has provided a value for each parameter.
-The compiler also assumes that these parameters are the only parameters that will be passed to the function.
-In short, the number of arguments given to a function has to match the number of parameters the function expects.
-
-```ts twoslash
-// @errors: 2554
-function buildName(firstName: string, lastName: string) {
-  return firstName + " " + lastName;
-}
-
-let result1 = buildName("Bob"); // error, too few parameters
-let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result3 = buildName("Bob", "Adams"); // ah, just right
-```
-
-In JavaScript, every parameter is optional, and users may leave them off as they see fit.
-When they do, their value is `undefined`.
-We can get this functionality in TypeScript by adding a `?` to the end of parameters we want to be optional.
-For example, let's say we want the last name parameter from above to be optional:
-
-```ts twoslash
-// @errors: 2554
-function buildName(firstName: string, lastName?: string) {
-  if (lastName) return firstName + " " + lastName;
-  else return firstName;
-}
-
-let result1 = buildName("Bob"); // works correctly now
-let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result3 = buildName("Bob", "Adams"); // ah, just right
-```
-
-Any optional parameters must follow required parameters.
-Had we wanted to make the first name optional, rather than the last name, we would need to change the order of parameters in the function, putting the first name last in the list.
-
-In TypeScript, we can also set a value that a parameter will be assigned if the user does not provide one, or if the user passes `undefined` in its place.
-These are called default-initialized parameters.
-Let's take the previous example and default the last name to `"Smith"`.
-
-```ts twoslash
-// @errors: 2554
-function buildName(firstName: string, lastName = "Smith") {
-  return firstName + " " + lastName;
-}
-
-let result1 = buildName("Bob"); // works correctly now, returns "Bob Smith"
-let result2 = buildName("Bob", undefined); // still works, also returns "Bob Smith"
-let result3 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result4 = buildName("Bob", "Adams"); // ah, just right
-```
-
-Default-initialized parameters that come after all required parameters are treated as optional, and just like optional parameters, can be omitted when calling their respective function.
-This means optional parameters and trailing default parameters will share commonality in their types, so both
-
-```ts
-function buildName(firstName: string, lastName?: string) {
-  // ...
-}
-```
-
-and
-
-```ts
-function buildName(firstName: string, lastName = "Smith") {
-  // ...
-}
-```
-
-share the same type `(firstName: string, lastName?: string) => string`.
-The default value of `lastName` disappears in the type, only leaving behind the fact that the parameter is optional.
-
-Unlike plain optional parameters, default-initialized parameters don't _need_ to occur after required parameters.
-If a default-initialized parameter comes before a required parameter, users need to explicitly pass `undefined` to get the default initialized value.
-For example, we could write our last example with only a default initializer on `firstName`:
-
-```ts twoslash
-// @errors: 2554
-function buildName(firstName = "Will", lastName: string) {
-  return firstName + " " + lastName;
-}
-
-let result1 = buildName("Bob"); // error, too few parameters
-let result2 = buildName("Bob", "Adams", "Sr."); // error, too many parameters
-let result3 = buildName("Bob", "Adams"); // okay and returns "Bob Adams"
-let result4 = buildName(undefined, "Adams"); // okay and returns "Will Adams"
-```
-
-## Rest Parameters
-
-Required, optional, and default parameters all have one thing in common: they talk about one parameter at a time.
-Sometimes, you want to work with multiple parameters as a group, or you may not know how many parameters a function will ultimately take.
-In JavaScript, you can work with the arguments directly using the `arguments` variable that is visible inside every function body.
-
-In TypeScript, you can gather these arguments together into a variable:
-
-```ts twoslash
-function buildName(firstName: string, ...restOfName: string[]) {
-  return firstName + " " + restOfName.join(" ");
-}
-
-// employeeName will be "Joseph Samuel Lucas MacKinzie"
-let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");
-```
-
-_Rest parameters_ are treated as a boundless number of optional parameters.
-When passing arguments for a rest parameter, you can use as many as you want; you can even pass none.
-The compiler will build an array of the arguments passed in with the name given after the ellipsis (`...`), allowing you to use it in your function.
-
-The ellipsis is also used in the type of the function with rest parameters:
-
-```ts twoslash
-function buildName(firstName: string, ...restOfName: string[]) {
-  return firstName + " " + restOfName.join(" ");
-}
-
-let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;
-```
-
-## `this`
-
-Learning how to use `this` in JavaScript is something of a rite of passage.
-Since TypeScript is a superset of JavaScript, TypeScript developers also need to learn how to use `this` and how to spot when it's not being used correctly.
-Fortunately, TypeScript lets you catch incorrect uses of `this` with a couple of techniques.
-If you need to learn how `this` works in JavaScript, though, first read Yehuda Katz's [Understanding JavaScript Function Invocation and "this"](http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/).
-Yehuda's article explains the inner workings of `this` very well, so we'll just cover the basics here.
-
-## `this` and arrow functions
-
-In JavaScript, `this` is a variable that's set when a function is called.
-This makes it a very powerful and flexible feature, but it comes at the cost of always having to know about the context that a function is executing in.
-This is notoriously confusing, especially when returning a function or passing a function as an argument.
-
-Let's look at an example:
-
-```ts twoslash
-// @strict: false
-let deck = {
-  suits: ["hearts", "spades", "clubs", "diamonds"],
-  cards: Array(52),
-  createCardPicker: function () {
-    return function () {
-      let pickedCard = Math.floor(Math.random() * 52);
-      let pickedSuit = Math.floor(pickedCard / 13);
-
-      return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
-    };
-  },
-};
-
-let cardPicker = deck.createCardPicker();
-let pickedCard = cardPicker();
-
-alert("card: " + pickedCard.card + " of " + pickedCard.suit);
-```
-
-Notice that `createCardPicker` is a function that itself returns a function.
-If we tried to run the example, we would get an error instead of the expected alert box.
-This is because the `this` being used in the function created by `createCardPicker` will be set to `window` instead of our `deck` object.
-That's because we call `cardPicker()` on its own.
-A top-level non-method syntax call like this will use `window` for `this`.
-(Note: under strict mode, `this` will be `undefined` rather than `window`).
-
-We can fix this by making sure the function is bound to the correct `this` before we return the function to be used later.
-This way, regardless of how it's later used, it will still be able to see the original `deck` object.
-To do this, we change the function expression to use the ECMAScript 6 arrow syntax.
-Arrow functions capture the `this` where the function is created rather than where it is invoked:
-
-```ts twoslash
-// @strict: false
-let deck = {
-  suits: ["hearts", "spades", "clubs", "diamonds"],
-  cards: Array(52),
-  createCardPicker: function () {
-    // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
-    return () => {
-      let pickedCard = Math.floor(Math.random() * 52);
-      let pickedSuit = Math.floor(pickedCard / 13);
-
-      return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
-    };
-  },
-};
-
-let cardPicker = deck.createCardPicker();
-let pickedCard = cardPicker();
-
-alert("card: " + pickedCard.card + " of " + pickedCard.suit);
-```
-
-Even better, TypeScript will warn you when you make this mistake if you pass the `--noImplicitThis` flag to the compiler.
-It will point out that `this` in `this.suits[pickedSuit]` is of type `any`.
-
-## `this` parameters
-
-Unfortunately, the type of `this.suits[pickedSuit]` is still `any`.
-That's because `this` comes from the function expression inside the object literal.
-To fix this, you can provide an explicit `this` parameter.
-`this` parameters are fake parameters that come first in the parameter list of a function:
-
-```ts
-function f(this: void) {
-  // make sure `this` is unusable in this standalone function
-}
-```
-
-Let's add a couple of interfaces to our example above, `Card` and `Deck`, to make the types clearer and easier to reuse:
-
-```ts twoslash
-interface Card {
-  suit: string;
-  card: number;
-}
-
-interface Deck {
-  suits: string[];
-  cards: number[];
-  createCardPicker(this: Deck): () => Card;
-}
-
-let deck: Deck = {
-  suits: ["hearts", "spades", "clubs", "diamonds"],
-  cards: Array(52),
-  // NOTE: The function now explicitly specifies that its callee must be of type Deck
-  createCardPicker: function (this: Deck) {
-    return () => {
-      let pickedCard = Math.floor(Math.random() * 52);
-      let pickedSuit = Math.floor(pickedCard / 13);
-
-      return { suit: this.suits[pickedSuit], card: pickedCard % 13 };
-    };
-  },
-};
-
-let cardPicker = deck.createCardPicker();
-let pickedCard = cardPicker();
-
-alert("card: " + pickedCard.card + " of " + pickedCard.suit);
-```
-
-Now TypeScript knows that `createCardPicker` expects to be called on a `Deck` object.
-That means that `this` is of type `Deck` now, not `any`, so `--noImplicitThis` will not cause any errors.
-
-### `this` parameters in callbacks
-
-You can also run into errors with `this` in callbacks, when you pass functions to a library that will later call them.
-Because the library that calls your callback will call it like a normal function, `this` will be `undefined`.
-With some work you can use `this` parameters to prevent errors with callbacks too.
-First, the library author needs to annotate the callback type with `this`:
-
-```ts twoslash
-interface UIElement {
-  addClickListener(onclick: (this: void, e: Event) => void): void;
-}
-```
-
-`this: void` means that `addClickListener` expects `onclick` to be a function that does not require a `this` type.
-Second, annotate your calling code with `this`:
-
-```ts twoslash
-// @strict: false
-// @errors: 2345
-interface UIElement {
-  addClickListener(onclick: (this: void, e: Event) => void): void;
-}
-interface Event {
-  message: string;
-}
-declare const uiElement: UIElement;
-// ---cut---
-class Handler {
-  info: string;
-  onClickBad(this: Handler, e: Event) {
-    // oops, used `this` here. using this callback would crash at runtime
-    this.info = e.message;
-  }
-}
-
-let h = new Handler();
-uiElement.addClickListener(h.onClickBad); // error!
-```
-
-With `this` annotated, you make it explicit that `onClickBad` must be called on an instance of `Handler`.
-Then TypeScript will detect that `addClickListener` requires a function that has `this: void`.
-To fix the error, change the type of `this`:
-
-```ts twoslash
-// @strict: false
-interface UIElement {
-  addClickListener(onclick: (this: void, e: Event) => void): void;
-}
-interface Event {
-  message: string;
-}
-declare const uiElement: UIElement;
-// ---cut---
-class Handler {
-  info: string;
-  onClickGood(this: void, e: Event) {
-    // can't use `this` here because it's of type void!
-    console.log("clicked!");
-  }
-}
-
-let h = new Handler();
-uiElement.addClickListener(h.onClickGood);
-```
-
-Because `onClickGood` specifies its `this` type as `void`, it is legal to pass to `addClickListener`.
-Of course, this also means that it can't use `this.info`.
-If you want both then you'll have to use an arrow function:
-
-```ts twoslash
-// @strict: false
-interface UIElement {
-  addClickListener(onclick: (this: void, e: Event) => void): void;
-}
-interface Event {
-  message: string;
-}
-declare const uiElement: UIElement;
-// ---cut---
-class Handler {
-  info: string;
-  onClickGood = (e: Event) => {
-    this.info = e.message;
-  };
-}
-```
-
-This works because arrow functions use the outer `this`, so you can always pass them to something that expects `this: void`.
-The downside is that one arrow function is created per object of type Handler.
-Methods, on the other hand, are only created once and attached to Handler's prototype.
-They are shared between all objects of type Handler.
-
-## Overloads
-
-JavaScript is inherently a very dynamic language.
-It's not uncommon for a single JavaScript function to return different types of objects based on the shape of the arguments passed in.
-
-```ts twoslash
-// @strict: false
-let suits = ["hearts", "spades", "clubs", "diamonds"];
-
-function pickCard(x: any): any {
-  // Check to see if we're working with an object/array
-  // if so, they gave us the deck and we'll pick the card
-  if (typeof x == "object") {
-    let pickedCard = Math.floor(Math.random() * x.length);
-    return pickedCard;
-  }
-  // Otherwise just let them pick the card
-  else if (typeof x == "number") {
-    let pickedSuit = Math.floor(x / 13);
-    return { suit: suits[pickedSuit], card: x % 13 };
-  }
-}
-
-let myDeck = [
-  { suit: "diamonds", card: 2 },
-  { suit: "spades", card: 10 },
-  { suit: "hearts", card: 4 },
-];
-
-let pickedCard1 = myDeck[pickCard(myDeck)];
-alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);
-
-let pickedCard2 = pickCard(15);
-alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
-```
-
-Here, the `pickCard` function will return two different things based on what the user has passed in.
-If the users passes in an object that represents the deck, the function will pick the card.
-If the user picks the card, we tell them which card they've picked.
-But how do we describe this to the type system?
-
-The answer is to supply multiple function types for the same function as a list of overloads.
-This list is what the compiler will use to resolve function calls.
-Let's create a list of overloads that describe what our `pickCard` accepts and what it returns.
-
-```ts twoslash
-let suits = ["hearts", "spades", "clubs", "diamonds"];
-
-function pickCard(x: { suit: string; card: number }[]): number;
-function pickCard(x: number): { suit: string; card: number };
-function pickCard(x: any): any {
-  // Check to see if we're working with an object/array
-  // if so, they gave us the deck and we'll pick the card
-  if (typeof x == "object") {
-    let pickedCard = Math.floor(Math.random() * x.length);
-    return pickedCard;
-  }
-  // Otherwise just let them pick the card
-  else if (typeof x == "number") {
-    let pickedSuit = Math.floor(x / 13);
-    return { suit: suits[pickedSuit], card: x % 13 };
-  }
-}
-
-let myDeck = [
-  { suit: "diamonds", card: 2 },
-  { suit: "spades", card: 10 },
-  { suit: "hearts", card: 4 },
-];
-
-let pickedCard1 = myDeck[pickCard(myDeck)];
-alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);
-
-let pickedCard2 = pickCard(15);
-alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);
-```
-
-With this change, the overloads now give us type checked calls to the `pickCard` function.
-
-In order for the compiler to pick the correct type check, it follows a similar process to the underlying JavaScript.
-It looks at the overload list and, proceeding with the first overload, attempts to call the function with the provided parameters.
-If it finds a match, it picks this overload as the correct overload.
-For this reason, it's customary to order overloads from most specific to least specific.
-
-Note that the `function pickCard(x): any` piece is not part of the overload list, so it only has two overloads: one that takes an object and one that takes a number.
-Calling `pickCard` with any other parameter types would cause an error.
diff --git a/docs/documentation/zh/handbook-v1/Generics.md b/docs/documentation/zh/handbook-v1/Generics.md
deleted file mode 100644
index a5f7bd40..00000000
--- a/docs/documentation/zh/handbook-v1/Generics.md
+++ /dev/null
@@ -1,376 +0,0 @@
----
-title: Generics
-layout: docs
-permalink: /docs/handbook/generics.html
-oneline: Introduction to TypeScript and Generics
-handbook: "true"
-deprecated_by: /docs/handbook/2/generics.html
----
-
-A major part of software engineering is building components that not only have well-defined and consistent APIs, but are also reusable.
-Components that are capable of working on the data of today as well as the data of tomorrow will give you the most flexible capabilities for building up large software systems.
-
-In languages like C# and Java, one of the main tools in the toolbox for creating reusable components is _generics_, that is, being able to create a component that can work over a variety of types rather than a single one.
-This allows users to consume these components and use their own types.
-
-## Hello World of Generics
-
-To start off, let's do the "hello world" of generics: the identity function.
-The identity function is a function that will return back whatever is passed in.
-You can think of this in a similar way to the `echo` command.
-
-Without generics, we would either have to give the identity function a specific type:
-
-```ts twoslash
-function identity(arg: number): number {
-  return arg;
-}
-```
-
-Or, we could describe the identity function using the `any` type:
-
-```ts twoslash
-function identity(arg: any): any {
-  return arg;
-}
-```
-
-While using `any` is certainly generic in that it will cause the function to accept any and all types for the type of `arg`, we actually are losing the information about what that type was when the function returns.
-If we passed in a number, the only information we have is that any type could be returned.
-
-Instead, we need a way of capturing the type of the argument in such a way that we can also use it to denote what is being returned.
-Here, we will use a _type variable_, a special kind of variable that works on types rather than values.
-
-```ts twoslash
-function identity(arg: T): T {
-  return arg;
-}
-```
-
-We've now added a type variable `T` to the identity function.
-This `T` allows us to capture the type the user provides (e.g. `number`), so that we can use that information later.
-Here, we use `T` again as the return type. On inspection, we can now see the same type is used for the argument and the return type.
-This allows us to traffic that type information in one side of the function and out the other.
-
-We say that this version of the `identity` function is generic, as it works over a range of types.
-Unlike using `any`, it's also just as precise (ie, it doesn't lose any information) as the first `identity` function that used numbers for the argument and return type.
-
-Once we've written the generic identity function, we can call it in one of two ways.
-The first way is to pass all of the arguments, including the type argument, to the function:
-
-```ts twoslash
-function identity(arg: T): T {
-  return arg;
-}
-// ---cut---
-let output = identity("myString");
-//       ^?
-```
-
-Here we explicitly set `T` to be `string` as one of the arguments to the function call, denoted using the `<>` around the arguments rather than `()`.
-
-The second way is also perhaps the most common. Here we use _type argument inference_ -- that is, we want the compiler to set the value of `T` for us automatically based on the type of the argument we pass in:
-
-```ts twoslash
-function identity(arg: T): T {
-  return arg;
-}
-// ---cut---
-let output = identity("myString");
-//       ^?
-```
-
-Notice that we didn't have to explicitly pass the type in the angle brackets (`<>`); the compiler just looked at the value `"myString"`, and set `T` to its type.
-While type argument inference can be a helpful tool to keep code shorter and more readable, you may need to explicitly pass in the type arguments as we did in the previous example when the compiler fails to infer the type, as may happen in more complex examples.
-
-## Working with Generic Type Variables
-
-When you begin to use generics, you'll notice that when you create generic functions like `identity`, the compiler will enforce that you use any generically typed parameters in the body of the function correctly.
-That is, that you actually treat these parameters as if they could be any and all types.
-
-Let's take our `identity` function from earlier:
-
-```ts twoslash
-function identity(arg: T): T {
-  return arg;
-}
-```
-
-What if we want to also log the length of the argument `arg` to the console with each call?
-We might be tempted to write this:
-
-```ts twoslash
-// @errors: 2339
-function loggingIdentity(arg: T): T {
-  console.log(arg.length);
-  return arg;
-}
-```
-
-When we do, the compiler will give us an error that we're using the `.length` member of `arg`, but nowhere have we said that `arg` has this member.
-Remember, we said earlier that these type variables stand in for any and all types, so someone using this function could have passed in a `number` instead, which does not have a `.length` member.
-
-Let's say that we've actually intended this function to work on arrays of `T` rather than `T` directly. Since we're working with arrays, the `.length` member should be available.
-We can describe this just like we would create arrays of other types:
-
-```ts twoslash
-function loggingIdentity(arg: T[]): T[] {
-  console.log(arg.length);
-  return arg;
-}
-```
-
-You can read the type of `loggingIdentity` as "the generic function `loggingIdentity` takes a type parameter `T`, and an argument `arg` which is an array of `T`s, and returns an array of `T`s."
-If we passed in an array of numbers, we'd get an array of numbers back out, as `T` would bind to `number`.
-This allows us to use our generic type variable `T` as part of the types we're working with, rather than the whole type, giving us greater flexibility.
-
-We can alternatively write the sample example this way:
-
-```ts twoslash
-function loggingIdentity(arg: Array): Array {
-  console.log(arg.length); // Array has a .length, so no more error
-  return arg;
-}
-```
-
-You may already be familiar with this style of type from other languages.
-In the next section, we'll cover how you can create your own generic types like `Array`.
-
-## Generic Types
-
-In previous sections, we created generic identity functions that worked over a range of types.
-In this section, we'll explore the type of the functions themselves and how to create generic interfaces.
-
-The type of generic functions is just like those of non-generic functions, with the type parameters listed first, similarly to function declarations:
-
-```ts twoslash
-function identity(arg: T): T {
-  return arg;
-}
-
-let myIdentity: (arg: T) => T = identity;
-```
-
-We could also have used a different name for the generic type parameter in the type, so long as the number of type variables and how the type variables are used line up.
-
-```ts twoslash
-function identity(arg: T): T {
-  return arg;
-}
-
-let myIdentity: (arg: U) => U = identity;
-```
-
-We can also write the generic type as a call signature of an object literal type:
-
-```ts twoslash
-function identity(arg: T): T {
-  return arg;
-}
-
-let myIdentity: { (arg: T): T } = identity;
-```
-
-Which leads us to writing our first generic interface.
-Let's take the object literal from the previous example and move it to an interface:
-
-```ts twoslash
-interface GenericIdentityFn {
-  (arg: T): T;
-}
-
-function identity(arg: T): T {
-  return arg;
-}
-
-let myIdentity: GenericIdentityFn = identity;
-```
-
-In a similar example, we may want to move the generic parameter to be a parameter of the whole interface.
-This lets us see what type(s) we're generic over (e.g. `Dictionary` rather than just `Dictionary`).
-This makes the type parameter visible to all the other members of the interface.
-
-```ts twoslash
-interface GenericIdentityFn {
-  (arg: T): T;
-}
-
-function identity(arg: T): T {
-  return arg;
-}
-
-let myIdentity: GenericIdentityFn = identity;
-```
-
-Notice that our example has changed to be something slightly different.
-Instead of describing a generic function, we now have a non-generic function signature that is a part of a generic type.
-When we use `GenericIdentityFn`, we now will also need to specify the corresponding type argument (here: `number`), effectively locking in what the underlying call signature will use.
-Understanding when to put the type parameter directly on the call signature and when to put it on the interface itself will be helpful in describing what aspects of a type are generic.
-
-In addition to generic interfaces, we can also create generic classes.
-Note that it is not possible to create generic enums and namespaces.
-
-## Generic Classes
-
-A generic class has a similar shape to a generic interface.
-Generic classes have a generic type parameter list in angle brackets (`<>`) following the name of the class.
-
-```ts twoslash
-// @strict: false
-class GenericNumber {
-  zeroValue: T;
-  add: (x: T, y: T) => T;
-}
-
-let myGenericNumber = new GenericNumber();
-myGenericNumber.zeroValue = 0;
-myGenericNumber.add = function (x, y) {
-  return x + y;
-};
-```
-
-This is a pretty literal use of the `GenericNumber` class, but you may have noticed that nothing is restricting it to only use the `number` type.
-We could have instead used `string` or even more complex objects.
-
-```ts twoslash
-// @strict: false
-class GenericNumber {
-  zeroValue: T;
-  add: (x: T, y: T) => T;
-}
-// ---cut---
-let stringNumeric = new GenericNumber();
-stringNumeric.zeroValue = "";
-stringNumeric.add = function (x, y) {
-  return x + y;
-};
-
-console.log(stringNumeric.add(stringNumeric.zeroValue, "test"));
-```
-
-Just as with interface, putting the type parameter on the class itself lets us make sure all of the properties of the class are working with the same type.
-
-As we covered in [our section on classes](/docs/handbook/classes.html), a class has two sides to its type: the static side and the instance side.
-Generic classes are only generic over their instance side rather than their static side, so when working with classes, static members can not use the class's type parameter.
-
-## Generic Constraints
-
-If you remember from an earlier example, you may sometimes want to write a generic function that works on a set of types where you have some knowledge about what capabilities that set of types will have.
-In our `loggingIdentity` example, we wanted to be able to access the `.length` property of `arg`, but the compiler could not prove that every type had a `.length` property, so it warns us that we can't make this assumption.
-
-```ts twoslash
-// @errors: 2339
-function loggingIdentity(arg: T): T {
-  console.log(arg.length);
-  return arg;
-}
-```
-
-Instead of working with any and all types, we'd like to constrain this function to work with any and all types that also have the `.length` property.
-As long as the type has this member, we'll allow it, but it's required to have at least this member.
-To do so, we must list our requirement as a constraint on what T can be.
-
-To do so, we'll create an interface that describes our constraint.
-Here, we'll create an interface that has a single `.length` property and then we'll use this interface and the `extends` keyword to denote our constraint:
-
-```ts twoslash
-interface Lengthwise {
-  length: number;
-}
-
-function loggingIdentity(arg: T): T {
-  console.log(arg.length); // Now we know it has a .length property, so no more error
-  return arg;
-}
-```
-
-Because the generic function is now constrained, it will no longer work over any and all types:
-
-```ts twoslash
-// @errors: 2345
-interface Lengthwise {
-  length: number;
-}
-
-function loggingIdentity(arg: T): T {
-  console.log(arg.length);
-  return arg;
-}
-// ---cut---
-loggingIdentity(3);
-```
-
-Instead, we need to pass in values whose type has all the required properties:
-
-```ts twoslash
-interface Lengthwise {
-  length: number;
-}
-
-function loggingIdentity(arg: T): T {
-  console.log(arg.length);
-  return arg;
-}
-// ---cut---
-loggingIdentity({ length: 10, value: 3 });
-```
-
-## Using Type Parameters in Generic Constraints
-
-You can declare a type parameter that is constrained by another type parameter.
-For example, here we'd like to get a property from an object given its name.
-We'd like to ensure that we're not accidentally grabbing a property that does not exist on the `obj`, so we'll place a constraint between the two types:
-
-```ts twoslash
-// @errors: 2345
-function getProperty(obj: T, key: K) {
-  return obj[key];
-}
-
-let x = { a: 1, b: 2, c: 3, d: 4 };
-
-getProperty(x, "a");
-getProperty(x, "m");
-```
-
-## Using Class Types in Generics
-
-When creating factories in TypeScript using generics, it is necessary to refer to class types by their constructor functions. For example,
-
-```ts twoslash
-function create(c: { new (): T }): T {
-  return new c();
-}
-```
-
-A more advanced example uses the prototype property to infer and constrain relationships between the constructor function and the instance side of class types.
-
-```ts twoslash
-// @strict: false
-class BeeKeeper {
-  hasMask: boolean;
-}
-
-class ZooKeeper {
-  nametag: string;
-}
-
-class Animal {
-  numLegs: number;
-}
-
-class Bee extends Animal {
-  keeper: BeeKeeper;
-}
-
-class Lion extends Animal {
-  keeper: ZooKeeper;
-}
-
-function createInstance(c: new () => A): A {
-  return new c();
-}
-
-createInstance(Lion).keeper.nametag;
-createInstance(Bee).keeper.hasMask;
-```
diff --git a/docs/documentation/zh/handbook-v1/Interfaces.md b/docs/documentation/zh/handbook-v1/Interfaces.md
deleted file mode 100644
index 4e2707cb..00000000
--- a/docs/documentation/zh/handbook-v1/Interfaces.md
+++ /dev/null
@@ -1,717 +0,0 @@
----
-title: Interfaces
-layout: docs
-permalink: /docs/handbook/interfaces.html
-oneline: How to write an interface with TypeScript
-handbook: "true"
-deprecated_by: /docs/handbook/2/objects.html
----
-
-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 subtyping".
-In TypeScript, interfaces fill the role of naming these types, and are a powerful way of defining contracts within your code as well as contracts with code outside of your project.
-
-## Our First Interface
-
-The easiest way to see how interfaces work is to start with a simple example:
-
-```ts twoslash
-function printLabel(labeledObj: { label: string }) {
-  console.log(labeledObj.label);
-}
-
-let myObj = { size: 10, label: "Size 10 Object" };
-printLabel(myObj);
-```
-
-The type checker checks the call to `printLabel`.
-The `printLabel` function has a single parameter that requires that the object passed in has a property called `label` of type `string`.
-Notice that our object actually has more properties than this, but the compiler only checks that _at least_ the ones required are present and match the types required.
-There are some cases where TypeScript isn't as lenient, which we'll cover in a bit.
-
-We can write the same example again, this time using an interface to describe the requirement of having the `label` property that is a string:
-
-```ts twoslash
-interface LabeledValue {
-  label: string;
-}
-
-function printLabel(labeledObj: LabeledValue) {
-  console.log(labeledObj.label);
-}
-
-let myObj = { size: 10, label: "Size 10 Object" };
-printLabel(myObj);
-```
-
-The interface `LabeledValue` is a name we can now use to describe the requirement in the previous example.
-It still represents having a single property called `label` that is of type `string`.
-Notice we didn't have to explicitly say that the object we pass to `printLabel` implements this interface like we might have to in other languages.
-Here, it's only the shape that matters. If the object we pass to the function meets the requirements listed, then it's allowed.
-
-It's worth pointing out that the type checker does not require that these properties come in any sort of order, only that the properties the interface requires are present and have the required type.
-
-## Optional Properties
-
-Not all properties of an interface may be required.
-Some exist under certain conditions or may not be there at all.
-These optional properties are popular when creating patterns like "option bags" where you pass an object to a function that only has a couple of properties filled in.
-
-Here's an example of this pattern:
-
-```ts twoslash
-interface SquareConfig {
-  color?: string;
-  width?: number;
-}
-
-function createSquare(config: SquareConfig): { color: string; area: number } {
-  let newSquare = { color: "white", area: 100 };
-  if (config.color) {
-    newSquare.color = config.color;
-  }
-  if (config.width) {
-    newSquare.area = config.width * config.width;
-  }
-  return newSquare;
-}
-
-let mySquare = createSquare({ color: "black" });
-```
-
-Interfaces with optional properties are written similar to other interfaces, with each optional property denoted by a `?` at the end of the property name in the declaration.
-
-The advantage of optional properties is that you can describe these possibly available properties while still also preventing use of properties that are not part of the interface.
-For example, had we mistyped the name of the `color` property in `createSquare`, we would get an error message letting us know:
-
-```ts twoslash
-// @errors: 2551
-interface SquareConfig {
-  color?: string;
-  width?: number;
-}
-
-function createSquare(config: SquareConfig): { color: string; area: number } {
-  let newSquare = { color: "white", area: 100 };
-  if (config.clor) {
-    // Error: Property 'clor' does not exist on type 'SquareConfig'
-    newSquare.color = config.clor;
-  }
-  if (config.width) {
-    newSquare.area = config.width * config.width;
-  }
-  return newSquare;
-}
-
-let mySquare = createSquare({ color: "black" });
-```
-
-## Readonly properties
-
-Some properties should only be modifiable when an object is first created.
-You can specify this by putting `readonly` before the name of the property:
-
-```ts twoslash
-interface Point {
-  readonly x: number;
-  readonly y: number;
-}
-```
-
-You can construct a `Point` by assigning an object literal.
-After the assignment, `x` and `y` can't be changed.
-
-```ts twoslash
-// @errors: 2540
-interface Point {
-  readonly x: number;
-  readonly y: number;
-}
-// ---cut---
-let p1: Point = { x: 10, y: 20 };
-p1.x = 5; // error!
-```
-
-TypeScript comes with a `ReadonlyArray` type that is the same as `Array` with all mutating methods removed, so you can make sure you don't change your arrays after creation:
-
-```ts twoslash
-// @errors: 2542 2339 2540 4104
-let a: number[] = [1, 2, 3, 4];
-let ro: ReadonlyArray = a;
-
-ro[0] = 12; // error!
-ro.push(5); // error!
-ro.length = 100; // error!
-a = ro; // error!
-```
-
-On the last line of the snippet you can see that even assigning the entire `ReadonlyArray` back to a normal array is illegal.
-You can still override it with a type assertion, though:
-
-```ts twoslash
-let a: number[] = [1, 2, 3, 4];
-let ro: ReadonlyArray = a;
-
-a = ro as number[];
-```
-
-### `readonly` vs `const`
-
-The easiest way to remember whether to use `readonly` or `const` is to ask whether you're using it on a variable or a property.
-Variables use `const` whereas properties use `readonly`.
-
-## Excess Property Checks
-
-In our first example using interfaces, TypeScript lets us pass `{ size: number; label: string; }` to something that only expected a `{ label: string; }`.
-We also just learned about optional properties, and how they're useful when describing so-called "option bags".
-
-However, combining the two naively would allow an error to sneak in. For example, taking our last example using `createSquare`:
-
-```ts twoslash
-// @errors: 2345 2739
-interface SquareConfig {
-  color?: string;
-  width?: number;
-}
-
-function createSquare(config: SquareConfig): { color: string; area: number } {
-  return {
-    color: config.color || "red",
-    area: config.width ? config.width * config.width : 20,
-  };
-}
-
-let mySquare = createSquare({ colour: "red", width: 100 });
-```
-
-Notice the given argument to `createSquare` is spelled _`colour`_ instead of `color`.
-In plain JavaScript, this sort of thing fails silently.
-
-You could argue that this program is correctly typed, since the `width` properties are compatible, there's no `color` property present, and the extra `colour` property is insignificant.
-
-However, TypeScript takes the stance that there's probably a bug in this code.
-Object literals get special treatment and undergo _excess property checking_ when assigning them to other variables, or passing them as arguments.
-If an object literal has any properties that the "target type" doesn't have, you'll get an error:
-
-```ts twoslash
-// @errors: 2345 2739
-interface SquareConfig {
-  color?: string;
-  width?: number;
-}
-
-function createSquare(config: SquareConfig): { color: string; area: number } {
-  return {
-    color: config.color || "red",
-    area: config.width ? config.width * config.width : 20,
-  };
-}
-// ---cut---
-let mySquare = createSquare({ colour: "red", width: 100 });
-```
-
-Getting around these checks is actually really simple.
-The easiest method is to just use a type assertion:
-
-```ts twoslash
-// @errors: 2345 2739
-interface SquareConfig {
-  color?: string;
-  width?: number;
-}
-
-function createSquare(config: SquareConfig): { color: string; area: number } {
-  return {
-    color: config.color || "red",
-    area: config.width ? config.width * config.width : 20,
-  };
-}
-// ---cut---
-let mySquare = createSquare({ width: 100, opacity: 0.5 } as SquareConfig);
-```
-
-However, a better approach might be to add a string index signature if you're sure that the object can have some extra properties that are used in some special way.
-If `SquareConfig` can have `color` and `width` properties with the above types, but could _also_ have any number of other properties, then we could define it like so:
-
-```ts twoslash
-interface SquareConfig {
-  color?: string;
-  width?: number;
-  [propName: string]: any;
-}
-```
-
-We'll discuss index signatures in a bit, but here we're saying a `SquareConfig` can have any number of properties, and as long as they aren't `color` or `width`, their types don't matter.
-
-One final way to get around these checks, which might be a bit surprising, is to assign the object to another variable:
-Since `squareOptions` won't undergo excess property checks, the compiler won't give you an error.
-
-```ts twoslash
-interface SquareConfig {
-  color?: string;
-  width?: number;
-  [propName: string]: any;
-}
-
-function createSquare(config: SquareConfig): { color: string; area: number } {
-  return {
-    color: config.color || "red",
-    area: config.width ? config.width * config.width : 20,
-  };
-}
-// ---cut---
-let squareOptions = { colour: "red", width: 100 };
-let mySquare = createSquare(squareOptions);
-```
-
-The above workaround will work as long as you have a common property between `squareOptions` and `SquareConfig`.
-In this example, it was the property `width`. It will however, fail if the variable does not have any common object property. For example:
-
-```ts twoslash
-// @errors: 2559
-interface SquareConfig {
-  color?: string;
-  width?: number;
-}
-
-function createSquare(config: SquareConfig): { color: string; area: number } {
-  return {
-    color: config.color || "red",
-    area: config.width ? config.width * config.width : 20,
-  };
-}
-// ---cut---
-let squareOptions = { colour: "red" };
-let mySquare = createSquare(squareOptions);
-```
-
-Keep in mind that for simple code like above, you probably shouldn't be trying to "get around" these checks.
-For more complex object literals that have methods and hold state, you might need to keep these techniques in mind, but a majority of excess property errors are actually bugs.
-That means if you're running into excess property checking problems for something like option bags, you might need to revise some of your type declarations.
-In this instance, if it's okay to pass an object with both a `color` or `colour` property to `createSquare`, you should fix up the definition of `SquareConfig` to reflect that.
-
-## Function Types
-
-Interfaces are capable of describing the wide range of shapes that JavaScript objects can take.
-In addition to describing an object with properties, interfaces are also capable of describing function types.
-
-To describe a function type with an interface, we give the interface a call signature.
-This is like a function declaration with only the parameter list and return type given. Each parameter in the parameter list requires both name and type.
-
-```ts twoslash
-interface SearchFunc {
-  (source: string, subString: string): boolean;
-}
-```
-
-Once defined, we can use this function type interface like we would other interfaces.
-Here, we show how you can create a variable of a function type and assign it a function value of the same type.
-
-```ts twoslash
-interface SearchFunc {
-  (source: string, subString: string): boolean;
-}
-// ---cut---
-let mySearch: SearchFunc;
-
-mySearch = function (source: string, subString: string): boolean {
-  let result = source.search(subString);
-  return result > -1;
-};
-```
-
-For function types to correctly type check, the names of the parameters do not need to match.
-We could have, for example, written the above example like this:
-
-```ts twoslash
-interface SearchFunc {
-  (source: string, subString: string): boolean;
-}
-// ---cut---
-let mySearch: SearchFunc;
-
-mySearch = function (src: string, sub: string): boolean {
-  let result = src.search(sub);
-  return result > -1;
-};
-```
-
-Function parameters are checked one at a time, with the type in each corresponding parameter position checked against each other.
-If you do not want to specify types at all, TypeScript's contextual typing can infer the argument types since the function value is assigned directly to a variable of type `SearchFunc`.
-Here, also, the return type of our function expression is implied by the values it returns (here `false` and `true`).
-
-```ts twoslash
-interface SearchFunc {
-  (source: string, subString: string): boolean;
-}
-// ---cut---
-let mySearch: SearchFunc;
-
-mySearch = function (src, sub) {
-  let result = src.search(sub);
-  return result > -1;
-};
-```
-
-Had the function expression returned numbers or strings, the type checker would have made an error that indicates return type doesn't match the return type described in the `SearchFunc` interface.
-
-```ts twoslash
-// @errors: 2322
-interface SearchFunc {
-  (source: string, subString: string): boolean;
-}
-// ---cut---
-let mySearch: SearchFunc;
-
-mySearch = function (src, sub) {
-  let result = src.search(sub);
-  return "string";
-};
-```
-
-## Indexable Types
-
-Similarly to how we can use interfaces to describe function types, we can also describe types that we can "index into" like `a[10]`, or `ageMap["daniel"]`.
-Indexable types have an _index signature_ that describes the types we can use to index into the object, along with the corresponding return types when indexing.
-
-Let's take an example:
-
-```ts twoslash
-interface StringArray {
-  [index: number]: string;
-}
-
-let myArray: StringArray;
-myArray = ["Bob", "Fred"];
-
-let myStr: string = myArray[0];
-```
-
-Above, we have a `StringArray` interface that has an index signature.
-This index signature states that when a `StringArray` is indexed with a `number`, it will return a `string`.
-
-There are four types of supported index signatures: string, number, symbol and template strings.
-It is possible to support many types of indexers, but the type returned from a numeric indexer must be a subtype of the type returned from the string indexer.
-
-This is because when indexing with a `number`, JavaScript will actually convert that to a `string` before indexing into an object.
-That means that indexing with `100` (a `number`) is the same thing as indexing with `"100"` (a `string`), so the two need to be consistent.
-
-```ts twoslash
-// @errors: 2413
-// @strictPropertyInitialization: false
-interface Animal {
-  name: string;
-}
-
-interface Dog extends Animal {
-  breed: string;
-}
-
-// Error: indexing with a numeric string might get you a completely separate type of Animal!
-interface NotOkay {
-  [x: number]: Animal;
-  [x: string]: Dog;
-}
-```
-
-While string index signatures are a powerful way to describe the "dictionary" pattern, they also enforce that all properties match their return type.
-This is because a string index declares that `obj.property` is also available as `obj["property"]`.
-In the following example, `name`'s type does not match the string index's type, and the type checker gives an error:
-
-```ts twoslash
-// @errors: 2411
-interface NumberDictionary {
-  [index: string]: number;
-
-  length: number; // ok, length is a number
-  name: string; // error, the type of 'name' is not a subtype of the indexer
-}
-```
-
-However, properties of different types are acceptable if the index signature is a union of the property types:
-
-```ts twoslash
-interface NumberOrStringDictionary {
-  [index: string]: number | string;
-
-  length: number; // ok, length is a number
-  name: string; // ok, name is a string
-}
-```
-
-Finally, you can make index signatures `readonly` in order to prevent assignment to their indices:
-
-```ts twoslash
-// @errors: 2542
-interface ReadonlyStringArray {
-  readonly [index: number]: string;
-}
-
-let myArray: ReadonlyStringArray = ["Alice", "Bob"];
-myArray[2] = "Mallory"; // error!
-```
-
-You can't set `myArray[2]` because the index signature is `readonly`.
-
-### Indexable Types with Template Strings
-
-A template string can be used to indicate that a particular pattern is allowed, but not all. For example, a HTTP headers object may have a set list of known headers and support any [custom defined properties](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) which are prefixed with `x-`.
-
-```ts twoslash
-// @errors: 2339
-
-interface HeadersResponse {
-  "content-type": string,
-  date: string,
-  "content-length": string
-
-  // Permit any property starting with 'data-'.
-  [headerName: `x-${string}`]: string;
-}
-
-function handleResponse(r: HeadersResponse) {
-  // Handle known, and x- prefixed
-  const type = r["content-type"]
-  const poweredBy = r["x-powered-by"]
-
-  // Unknown keys without the prefix raise errors
-  const origin = r.origin
-}
-```
-
-## Class Types
-
-### Implementing an interface
-
-One of the most common uses of interfaces in languages like C# and Java, that of explicitly enforcing that a class meets a particular contract, is also possible in TypeScript.
-
-```ts twoslash
-interface ClockInterface {
-  currentTime: Date;
-}
-
-class Clock implements ClockInterface {
-  currentTime: Date = new Date();
-  constructor(h: number, m: number) {}
-}
-```
-
-You can also describe methods in an interface that are implemented in the class, as we do with `setTime` in the below example:
-
-```ts twoslash
-// @strictPropertyInitialization: false
-interface ClockInterface {
-  currentTime: Date;
-  setTime(d: Date): void;
-}
-
-class Clock implements ClockInterface {
-  currentTime: Date = new Date();
-  setTime(d: Date) {
-    this.currentTime = d;
-  }
-  constructor(h: number, m: number) {}
-}
-```
-
-Interfaces describe the public side of the class, rather than both the public and private side.
-This prohibits you from using them to check that a class also has particular types for the private side of the class instance.
-
-### Difference between the static and instance sides of classes
-
-When working with classes and interfaces, it helps to keep in mind that a class has _two_ types: the type of the static side and the type of the instance side.
-You may notice that if you create an interface with a construct signature and try to create a class that implements this interface you get an error:
-
-```ts twoslash
-// @errors: 7013 2420 2564
-// @strictPropertyInitialization: false
-// @noImplicitAny: false
-interface ClockConstructor {
-  new (hour: number, minute: number);
-}
-
-class Clock implements ClockConstructor {
-  currentTime: Date;
-  constructor(h: number, m: number) {}
-}
-```
-
-This is because when a class implements an interface, only the instance side of the class is checked.
-Since the constructor sits in the static side, it is not included in this check.
-
-Instead, you would need to work with the static side of the class directly.
-In this example, we define two interfaces, `ClockConstructor` for the constructor and `ClockInterface` for the instance methods.
-Then, for convenience, we define a constructor function `createClock` that creates instances of the type that is passed to it:
-
-```ts twoslash
-interface ClockConstructor {
-  new (hour: number, minute: number): ClockInterface;
-}
-
-interface ClockInterface {
-  tick(): void;
-}
-
-function createClock(
-  ctor: ClockConstructor,
-  hour: number,
-  minute: number
-): ClockInterface {
-  return new ctor(hour, minute);
-}
-
-class DigitalClock implements ClockInterface {
-  constructor(h: number, m: number) {}
-  tick() {
-    console.log("beep beep");
-  }
-}
-
-class AnalogClock implements ClockInterface {
-  constructor(h: number, m: number) {}
-  tick() {
-    console.log("tick tock");
-  }
-}
-
-let digital = createClock(DigitalClock, 12, 17);
-let analog = createClock(AnalogClock, 7, 32);
-```
-
-Because `createClock`'s first parameter is of type `ClockConstructor`, in `createClock(AnalogClock, 7, 32)`, it checks that `AnalogClock` has the correct constructor signature.
-
-Another simple way is to use class expressions:
-
-```ts twoslash
-// @strictPropertyInitialization: false
-// @noImplicitAny: false
-interface ClockConstructor {
-  new (hour: number, minute: number): ClockInterface;
-}
-
-interface ClockInterface {
-  tick(): void;
-}
-
-const Clock: ClockConstructor = class Clock implements ClockInterface {
-  constructor(h: number, m: number) {}
-  tick() {
-    console.log("beep beep");
-  }
-};
-
-let clock = new Clock(12, 17);
-clock.tick();
-```
-
-## Extending Interfaces
-
-Like classes, interfaces can extend each other.
-This allows you to copy the members of one interface into another, which gives you more flexibility in how you separate your interfaces into reusable components.
-
-```ts twoslash
-interface Shape {
-  color: string;
-}
-
-interface Square extends Shape {
-  sideLength: number;
-}
-
-let square = {} as Square;
-square.color = "blue";
-square.sideLength = 10;
-```
-
-An interface can extend multiple interfaces, creating a combination of all of the interfaces.
-
-```ts twoslash
-interface Shape {
-  color: string;
-}
-
-interface PenStroke {
-  penWidth: number;
-}
-
-interface Square extends Shape, PenStroke {
-  sideLength: number;
-}
-
-let square = {} as Square;
-square.color = "blue";
-square.sideLength = 10;
-square.penWidth = 5.0;
-```
-
-## Hybrid Types
-
-As we mentioned earlier, interfaces can describe the rich types present in real world JavaScript.
-Because of JavaScript's dynamic and flexible nature, you may occasionally encounter an object that works as a combination of some of the types described above.
-
-One such example is an object that acts as both a function and an object, with additional properties:
-
-```ts twoslash
-interface Counter {
-  (start: number): string;
-  interval: number;
-  reset(): void;
-}
-
-function getCounter(): Counter {
-  let counter = function (start: number) {} as Counter;
-  counter.interval = 123;
-  counter.reset = function () {};
-  return counter;
-}
-
-let c = getCounter();
-c(10);
-c.reset();
-c.interval = 5.0;
-```
-
-When interacting with 3rd-party JavaScript, you may need to use patterns like the above to fully describe the shape of the type.
-
-## Interfaces Extending Classes
-
-When an interface type extends a class type it inherits the members of the class but not their implementations.
-It is as if the interface had declared all of the members of the class without providing an implementation.
-Interfaces inherit even the private and protected members of a base class.
-This means that when you create an interface that extends a class with private or protected members, that interface type can only be implemented by that class or a subclass of it.
-
-This is useful when you have a large inheritance hierarchy, but want to specify that your code works with only subclasses that have certain properties.
-The subclasses don't have to be related besides inheriting from the base class.
-For example:
-
-```ts twoslash
-// @errors: 2300 2420 2300
-class Control {
-  private state: any;
-}
-
-interface SelectableControl extends Control {
-  select(): void;
-}
-
-class Button extends Control implements SelectableControl {
-  select() {}
-}
-
-class TextBox extends Control {
-  select() {}
-}
-
-class ImageControl implements SelectableControl {
-  private state: any;
-  select() {}
-}
-```
-
-In the above example, `SelectableControl` contains all of the members of `Control`, including the private `state` property.
-Since `state` is a private member it is only possible for descendants of `Control` to implement `SelectableControl`.
-This is because only descendants of `Control` will have a `state` private member that originates in the same declaration, which is a requirement for private members to be compatible.
-
-Within the `Control` class it is possible to access the `state` private member through an instance of `SelectableControl`.
-Effectively, a `SelectableControl` acts like a `Control` that is known to have a `select` method.
-The `Button` and `TextBox` classes are subtypes of `SelectableControl` (because they both inherit from `Control` and have a `select` method). The `ImageControl` class has its own `state` private member rather than extending `Control`, so it cannot implement `SelectableControl`.
diff --git a/docs/documentation/zh/handbook-v1/Literal Types.md b/docs/documentation/zh/handbook-v1/Literal Types.md
deleted file mode 100644
index 5925d248..00000000
--- a/docs/documentation/zh/handbook-v1/Literal Types.md	
+++ /dev/null
@@ -1,120 +0,0 @@
----
-title: Literal Types
-layout: docs
-permalink: /docs/handbook/literal-types.html
-oneline: Using literal types with TypeScript
-handbook: "true"
-deprecated_by: /docs/handbook/2/everyday-types.html#literal-types
----
-
-A literal is a more concrete sub-type of a collective type.
-What this means is that `"Hello World"` is a `string`, but a `string` is not `"Hello World"` inside the type system.
-
-There are three sets of literal types available in TypeScript today: strings, numbers, and booleans; by using literal types you can allow an exact value which a string, number, or boolean must have.
-
-## Literal Narrowing
-
-When you declare a variable via `var` or `let`, you are telling the compiler that there is the chance that this variable will change its contents.
-In contrast, using `const` to declare a variable will inform TypeScript that this object will never change.
-
-```ts twoslash
-// We're making a guarantee that this variable
-// helloWorld will never change, by using const.
-
-// So, TypeScript sets the type to be "Hello World", not string
-const helloWorld = "Hello World";
-
-// On the other hand, a let can change, and so the compiler declares it a string
-let hiWorld = "Hi World";
-```
-
-The process of going from an infinite number of potential cases (there are an infinite number of possible string values) to a smaller, finite number of potential case (in `helloWorld`'s case: 1) is called narrowing.
-
-## String Literal Types
-
-In practice string literal types combine nicely with union types, type guards, and type aliases.
-You can use these features together to get enum-like behavior with strings.
-
-```ts twoslash
-// @errors: 2345
-type Easing = "ease-in" | "ease-out" | "ease-in-out";
-
-class UIElement {
-  animate(dx: number, dy: number, easing: Easing) {
-    if (easing === "ease-in") {
-      // ...
-    } else if (easing === "ease-out") {
-    } else if (easing === "ease-in-out") {
-    } else {
-      // It's possible that someone could reach this
-      // by ignoring your types though.
-    }
-  }
-}
-
-let button = new UIElement();
-button.animate(0, 0, "ease-in");
-button.animate(0, 0, "uneasy");
-```
-
-You can pass any of the three allowed strings, but any other string will give the error
-
-```
-Argument of type '"uneasy"' is not assignable to parameter of type '"ease-in" | "ease-out" | "ease-in-out"'
-```
-
-String literal types can be used in the same way to distinguish overloads:
-
-```ts
-function createElement(tagName: "img"): HTMLImageElement;
-function createElement(tagName: "input"): HTMLInputElement;
-// ... more overloads ...
-function createElement(tagName: string): Element {
-  // ... code goes here ...
-}
-```
-
-## Numeric Literal Types
-
-TypeScript also has numeric literal types, which act the same as the string literals above.
-
-```ts twoslash
-function rollDice(): 1 | 2 | 3 | 4 | 5 | 6 {
-  return (Math.floor(Math.random() * 6) + 1) as 1 | 2 | 3 | 4 | 5 | 6;
-}
-
-const result = rollDice();
-```
-
-A common case for their use is for describing config values:
-
-```ts twoslash
-/** Creates a map centered at loc/lat */
-declare function setupMap(config: MapConfig): void;
-// ---cut---
-interface MapConfig {
-  lng: number;
-  lat: number;
-  tileSize: 8 | 16 | 32;
-}
-
-setupMap({ lng: -73.935242, lat: 40.73061, tileSize: 16 });
-```
-
-## Boolean Literal Types
-
-TypeScript also has boolean literal types. You might use these to constrain object values whose properties are interrelated.
-
-```ts twoslash
-interface ValidationSuccess {
-  isValid: true;
-  reason: null;
-}
-
-interface ValidationFailure {
-  isValid: false;
-  reason: string;
-}
-
-type ValidationResult = ValidationSuccess | ValidationFailure;
-```
diff --git a/docs/documentation/zh/handbook-v1/Unions and Intersections.md b/docs/documentation/zh/handbook-v1/Unions and Intersections.md
deleted file mode 100644
index 2246dd0a..00000000
--- a/docs/documentation/zh/handbook-v1/Unions and Intersections.md	
+++ /dev/null
@@ -1,412 +0,0 @@
----
-title: Unions and Intersection Types
-layout: docs
-permalink: /docs/handbook/unions-and-intersections.html
-oneline: How to use unions and intersection types in TypeScript
-handbook: "true"
-deprecated_by: /docs/handbook/2/everyday-types.html#union-types
-# prettier-ignore
-deprecation_redirects: [
-  discriminating-unions, /docs/handbook/2/narrowing.html#discriminated-unions
-]
----
-
-So far, the handbook has covered types which are atomic objects.
-However, as you model more types you find yourself looking for tools which let you compose or combine existing types instead of creating them from scratch.
-
-Intersection and Union types are one of the ways in which you can compose types.
-
-## Union Types
-
-Occasionally, you'll run into a library that expects a parameter to be either a `number` or a `string`.
-For instance, take the following function:
-
-```ts twoslash
-/**
- * Takes a string and adds "padding" to the left.
- * If 'padding' is a string, then 'padding' is appended to the left side.
- * If 'padding' is a number, then that number of spaces is added to the left side.
- */
-function padLeft(value: string, padding: any) {
-  if (typeof padding === "number") {
-    return Array(padding + 1).join(" ") + value;
-  }
-  if (typeof padding === "string") {
-    return padding + value;
-  }
-  throw new Error(`Expected string or number, got '${typeof padding}'.`);
-}
-
-padLeft("Hello world", 4); // returns "    Hello world"
-```
-
-The problem with `padLeft` in the above example is that its `padding` parameter is typed as `any`.
-That means that we can call it with an argument that's neither a `number` nor a `string`, but TypeScript will be okay with it.
-
-```ts twoslash
-declare function padLeft(value: string, padding: any): string;
-// ---cut---
-// passes at compile time, fails at runtime.
-let indentedString = padLeft("Hello world", true);
-```
-
-In traditional object-oriented code, we might abstract over the two types by creating a hierarchy of types.
-While this is much more explicit, it's also a little bit overkill.
-One of the nice things about the original version of `padLeft` was that we were able to just pass in primitives.
-That meant that usage was simple and concise.
-This new approach also wouldn't help if we were just trying to use a function that already exists elsewhere.
-
-Instead of `any`, we can use a _union type_ for the `padding` parameter:
-
-```ts twoslash
-// @errors: 2345
-/**
- * Takes a string and adds "padding" to the left.
- * If 'padding' is a string, then 'padding' is appended to the left side.
- * If 'padding' is a number, then that number of spaces is added to the left side.
- */
-function padLeft(value: string, padding: string | number) {
-  // ...
-}
-
-let indentedString = padLeft("Hello world", true);
-```
-
-A union type describes a value that can be one of several types.
-We use the vertical bar (`|`) to separate each type, so `number | string | boolean` is the type of a value that can be a `number`, a `string`, or a `boolean`.
-
-## Unions with Common Fields
-
-If we have a value that is a union type, we can only access members that are common to all types in the union.
-
-```ts twoslash
-// @errors: 2339
-
-interface Bird {
-  fly(): void;
-  layEggs(): void;
-}
-
-interface Fish {
-  swim(): void;
-  layEggs(): void;
-}
-
-declare function getSmallPet(): Fish | Bird;
-
-let pet = getSmallPet();
-pet.layEggs();
-
-// Only available in one of the two possible types
-pet.swim();
-```
-
-Union types can be a bit tricky here, but it just takes a bit of intuition to get used to.
-If a value has the type `A | B`, we only know for _certain_ that it has members that both `A` _and_ `B` have.
-In this example, `Bird` has a member named `fly`.
-We can't be sure whether a variable typed as `Bird | Fish` has a `fly` method.
-If the variable is really a `Fish` at runtime, then calling `pet.fly()` will fail.
-
-## Discriminating Unions
-
-A common technique for working with unions is to have a single field which uses literal types which you can use to let TypeScript narrow down the possible current type. For example, we're going to create a union of three types which have a single shared field.
-
-```ts
-type NetworkLoadingState = {
-  state: "loading";
-};
-
-type NetworkFailedState = {
-  state: "failed";
-  code: number;
-};
-
-type NetworkSuccessState = {
-  state: "success";
-  response: {
-    title: string;
-    duration: number;
-    summary: string;
-  };
-};
-
-// Create a type which represents only one of the above types
-// but you aren't sure which it is yet.
-type NetworkState =
-  | NetworkLoadingState
-  | NetworkFailedState
-  | NetworkSuccessState;
-```
-
-
-
-All of the above types have a field named `state`, and then they also have their own fields:
-
-
-  
-    
-      
-      
-      
-    
-    
-      
-      
-      
-    
-    
-      
-      
-      
-    
-    
-
NetworkLoadingStateNetworkFailedStateNetworkSuccessState
statestatestate
coderesponse
- -Given the `state` field is common in every type inside `NetworkState` - it is safe for your code to access without an existence check. - -With `state` as a literal type, you can compare the value of `state` to the equivalent string and TypeScript will know which type is currently being used. - - - - - - - - - - - - - - -
NetworkLoadingStateNetworkFailedStateNetworkSuccessState
"loading""failed""success"
- -In this case, you can use a `switch` statement to narrow down which type is represented at runtime: - -```ts twoslash -// @errors: 2339 -type NetworkLoadingState = { - state: "loading"; -}; - -type NetworkFailedState = { - state: "failed"; - code: number; -}; - -type NetworkSuccessState = { - state: "success"; - response: { - title: string; - duration: number; - summary: string; - }; -}; -// ---cut--- -type NetworkState = - | NetworkLoadingState - | NetworkFailedState - | NetworkSuccessState; - -function logger(state: NetworkState): string { - // Right now TypeScript does not know which of the three - // potential types state could be. - - // Trying to access a property which isn't shared - // across all types will raise an error - state.code; - - // By switching on state, TypeScript can narrow the union - // down in code flow analysis - switch (state.state) { - case "loading": - return "Downloading..."; - case "failed": - // The type must be NetworkFailedState here, - // so accessing the `code` field is safe - return `Error ${state.code} downloading`; - case "success": - return `Downloaded ${state.response.title} - ${state.response.summary}`; - } -} -``` - -## Union Exhaustiveness checking - -We would like the compiler to tell us when we don't cover all variants of the discriminated union. -For example, if we add `NetworkFromCachedState` to `NetworkState`, we need to update `logger` as well: - -```ts twoslash -// @errors: 2366 -type NetworkLoadingState = { state: "loading" }; -type NetworkFailedState = { state: "failed"; code: number }; -type NetworkSuccessState = { - state: "success"; - response: { - title: string; - duration: number; - summary: string; - }; -}; -// ---cut--- -type NetworkFromCachedState = { - state: "from_cache"; - id: string; - response: NetworkSuccessState["response"]; -}; - -type NetworkState = - | NetworkLoadingState - | NetworkFailedState - | NetworkSuccessState - | NetworkFromCachedState; - -function logger(s: NetworkState) { - switch (s.state) { - case "loading": - return "loading request"; - case "failed": - return `failed with code ${s.code}`; - case "success": - return "got response"; - } -} -``` - -There are two ways to do this. -The first is to turn on `--strictNullChecks` and specify a return type: - -```ts twoslash -// @errors: 2366 -type NetworkLoadingState = { state: "loading" }; -type NetworkFailedState = { state: "failed"; code: number }; -type NetworkSuccessState = { state: "success" }; -type NetworkFromCachedState = { state: "from_cache" }; - -type NetworkState = - | NetworkLoadingState - | NetworkFailedState - | NetworkSuccessState - | NetworkFromCachedState; - -// ---cut--- -function logger(s: NetworkState): string { - switch (s.state) { - case "loading": - return "loading request"; - case "failed": - return `failed with code ${s.code}`; - case "success": - return "got response"; - } -} -``` - -Because the `switch` is no longer exhaustive, TypeScript is aware that the function could sometimes return `undefined`. -If you have an explicit return type `string`, then you will get an error that the return type is actually `string | undefined`. -However, this method is quite subtle and, besides, [`--strictNullChecks`](/tsconfig#strictNullChecks) does not always work with old code. - -The second method uses the `never` type that the compiler uses to check for exhaustiveness: - -```ts twoslash -// @errors: 2345 -type NetworkLoadingState = { state: "loading" }; -type NetworkFailedState = { state: "failed"; code: number }; -type NetworkSuccessState = { state: "success" }; -type NetworkFromCachedState = { state: "from_cache" }; - -type NetworkState = - | NetworkLoadingState - | NetworkFailedState - | NetworkSuccessState - | NetworkFromCachedState; -// ---cut--- -function assertNever(x: never): never { - throw new Error("Unexpected object: " + x); -} - -function logger(s: NetworkState): string { - switch (s.state) { - case "loading": - return "loading request"; - case "failed": - return `failed with code ${s.code}`; - case "success": - return "got response"; - default: - return assertNever(s); - } -} -``` - -Here, `assertNever` checks that `s` is of type `never` — the type that's left after all other cases have been removed. -If you forget a case, then `s` will have a real type and you will get a type error. -This method requires you to define an extra function, but it's much more obvious when you forget it because the error message includes the missing type name. - -## Intersection Types - -Intersection types are closely related to union types, but they are used very differently. -An intersection type combines multiple types into one. -This allows you to add together existing types to get a single type that has all the features you need. -For example, `Person & Serializable & Loggable` is a type which is all of `Person` _and_ `Serializable` _and_ `Loggable`. -That means an object of this type will have all members of all three types. - -For example, if you had networking requests with consistent error handling then you could separate out the error handling into its own type which is merged with types which correspond to a single response type. - -```ts twoslash -interface ErrorHandling { - success: boolean; - error?: { message: string }; -} - -interface ArtworksData { - artworks: { title: string }[]; -} - -interface ArtistsData { - artists: { name: string }[]; -} - -// These interfaces are composed to have -// consistent error handling, and their own data. - -type ArtworksResponse = ArtworksData & ErrorHandling; -type ArtistsResponse = ArtistsData & ErrorHandling; - -const handleArtistsResponse = (response: ArtistsResponse) => { - if (response.error) { - console.error(response.error.message); - return; - } - - console.log(response.artists); -}; -``` diff --git a/docs/documentation/zh/handbook-v2/Basics.md b/docs/documentation/zh/handbook-v2/Basics.md deleted file mode 100644 index c7435c94..00000000 --- a/docs/documentation/zh/handbook-v2/Basics.md +++ /dev/null @@ -1,440 +0,0 @@ ---- -title: The Basics -layout: docs -permalink: /docs/handbook/2/basic-types.html -oneline: "Step one in learning TypeScript: The basic types." -preamble: > -

Welcome to the first page of the handbook, if this is your first experience with TypeScript - you may want to start at one of the 'Getting Started' guides ---- - -Each and every value in JavaScript has a set of behaviors you can observe from running different operations. -That sounds abstract, but as a quick example, consider some operations we might run on a variable named `message`. - -```js -// Accessing the property 'toLowerCase' -// on 'message' and then calling it -message.toLowerCase(); - -// Calling 'message' -message(); -``` - -If we break this down, the first runnable line of code accesses a property called `toLowerCase` and then calls it. -The second one tries to call `message` directly. - -But assuming we don't know the value of `message` - and that's pretty common - we can't reliably say what results we'll get from trying to run any of this code. -The behavior of each operation depends entirely on what value we had in the first place. - -- Is `message` callable? -- Does it have a property called `toLowerCase` on it? -- If it does, is `toLowerCase` even callable? -- If both of these values are callable, what do they return? - -The answers to these questions are usually things we keep in our heads when we write JavaScript, and we have to hope we got all the details right. - -Let's say `message` was defined in the following way. - -```js -const message = "Hello World!"; -``` - -As you can probably guess, if we try to run `message.toLowerCase()`, we'll get the same string only in lower-case. - -What about that second line of code? -If you're familiar with JavaScript, you'll know this fails with an exception: - -```txt -TypeError: message is not a function -``` - -It'd be great if we could avoid mistakes like this. - -When we run our code, the way that our JavaScript runtime chooses what to do is by figuring out the _type_ of the value - what sorts of behaviors and capabilities it has. -That's part of what that `TypeError` is alluding to - it's saying that the string `"Hello World!"` cannot be called as a function. - -For some values, such as the primitives `string` and `number`, we can identify their type at runtime using the `typeof` operator. -But for other things like functions, there's no corresponding runtime mechanism to identify their types. -For example, consider this function: - -```js -function fn(x) { - return x.flip(); -} -``` - -We can _observe_ by reading the code that this function will only work if given an object with a callable `flip` property, but JavaScript doesn't surface this information in a way that we can check while the code is running. -The only way in pure JavaScript to tell what `fn` does with a particular value is to call it and see what happens. -This kind of behavior makes it hard to predict what code will do before it runs, which means it's harder to know what your code is going to do while you're writing it. - -Seen in this way, a _type_ is the concept of describing which values can be passed to `fn` and which will crash. -JavaScript only truly provides _dynamic_ typing - running the code to see what happens. - -The alternative is to use a _static_ type system to make predictions about what code is expected _before_ it runs. - -## Static type-checking - -Think back to that `TypeError` we got earlier from trying to call a `string` as a function. -_Most people_ don't like to get any sorts of errors when running their code - those are considered bugs! -And when we write new code, we try our best to avoid introducing new bugs. - -If we add just a bit of code, save our file, re-run the code, and immediately see the error, we might be able to isolate the problem quickly; but that's not always the case. -We might not have tested the feature thoroughly enough, so we might never actually run into a potential error that would be thrown! -Or if we were lucky enough to witness the error, we might have ended up doing large refactorings and adding a lot of different code that we're forced to dig through. - -Ideally, we could have a tool that helps us find these bugs _before_ our code runs. -That's what a static type-checker like TypeScript does. -_Static types systems_ describe the shapes and behaviors of what our values will be when we run our programs. -A type-checker like TypeScript uses that information and tells us when things might be going off the rails. - -```ts twoslash -// @errors: 2349 -const message = "hello!"; - -message(); -``` - -Running that last sample with TypeScript will give us an error message before we run the code in the first place. - -## Non-exception Failures - -So far we've been discussing certain things like runtime errors - cases where the JavaScript runtime tells us that it thinks something is nonsensical. -Those cases come up because [the ECMAScript specification](https://tc39.github.io/ecma262/) has explicit instructions on how the language should behave when it runs into something unexpected. - -For example, the specification says that trying to call something that isn't callable should throw an error. -Maybe that sounds like "obvious behavior", but you could imagine that accessing a property that doesn't exist on an object should throw an error too. -Instead, JavaScript gives us different behavior and returns the value `undefined`: - -```js -const user = { - name: "Daniel", - age: 26, -}; - -user.location; // returns undefined -``` - -Ultimately, a static type system has to make the call over what code should be flagged as an error in its system, even if it's "valid" JavaScript that won't immediately throw an error. -In TypeScript, the following code produces an error about `location` not being defined: - -```ts twoslash -// @errors: 2339 -const user = { - name: "Daniel", - age: 26, -}; - -user.location; -``` - -While sometimes that implies a trade-off in what you can express, the intent is to catch legitimate bugs in our programs. -And TypeScript catches _a lot_ of legitimate bugs. - -For example: typos, - -```ts twoslash -// @noErrors -const announcement = "Hello World!"; - -// How quickly can you spot the typos? -announcement.toLocaleLowercase(); -announcement.toLocalLowerCase(); - -// We probably meant to write this... -announcement.toLocaleLowerCase(); -``` - -uncalled functions, - -```ts twoslash -// @noUnusedLocals -// @errors: 2365 -function flipCoin() { - // Meant to be Math.random() - return Math.random < 0.5; -} -``` - -or basic logic errors. - -```ts twoslash -// @errors: 2367 -const value = Math.random() < 0.5 ? "a" : "b"; -if (value !== "a") { - // ... -} else if (value === "b") { - // Oops, unreachable -} -``` - -## Types for Tooling - -TypeScript can catch bugs when we make mistakes in our code. -That's great, but TypeScript can _also_ prevent us from making those mistakes in the first place. - -The type-checker has information to check things like whether we're accessing the right properties on variables and other properties. -Once it has that information, it can also start _suggesting_ which properties you might want to use. - -That means TypeScript can be leveraged for editing code too, and the core type-checker can provide error messages and code completion as you type in the editor. -That's part of what people often refer to when they talk about tooling in TypeScript. - - -```ts twoslash -// @noErrors -// @esModuleInterop -import express from "express"; -const app = express(); - -app.get("/", function (req, res) { - res.sen -// ^| -}); - -app.listen(3000); -``` - -TypeScript takes tooling seriously, and that goes beyond completions and errors as you type. -An editor that supports TypeScript can deliver "quick fixes" to automatically fix errors, refactorings to easily re-organize code, and useful navigation features for jumping to definitions of a variable, or finding all references to a given variable. -All of this is built on top of the type-checker and is fully cross-platform, so it's likely that [your favorite editor has TypeScript support available](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Editor-Support). - -## `tsc`, the TypeScript compiler - -We've been talking about type-checking, but we haven't yet used our type-_checker_. -Let's get acquainted with our new friend `tsc`, the TypeScript compiler. -First we'll need to grab it via npm. - -```sh -npm install -g typescript -``` - -> This installs the TypeScript Compiler `tsc` globally. -> You can use `npx` or similar tools if you'd prefer to run `tsc` from a local `node_modules` package instead. - -Now let's move to an empty folder and try writing our first TypeScript program: `hello.ts`: - -```ts twoslash -// Greets the world. -console.log("Hello world!"); -``` - -Notice there are no frills here; this "hello world" program looks identical to what you'd write for a "hello world" program in JavaScript. -And now let's type-check it by running the command `tsc` which was installed for us by the `typescript` package. - -```sh -tsc hello.ts -``` - -Tada! - -Wait, "tada" _what_ exactly? -We ran `tsc` and nothing happened! -Well, there were no type errors, so we didn't get any output in our console since there was nothing to report. - -But check again - we got some _file_ output instead. -If we look in our current directory, we'll see a `hello.js` file next to `hello.ts`. -That's the output from our `hello.ts` file after `tsc` _compiles_ or _transforms_ it into a plain JavaScript file. -And if we check the contents, we'll see what TypeScript spits out after it processes a `.ts` file: - -```js -// Greets the world. -console.log("Hello world!"); -``` - -In this case, there was very little for TypeScript to transform, so it looks identical to what we wrote. -The compiler tries to emit clean readable code that looks like something a person would write. -While that's not always so easy, TypeScript indents consistently, is mindful of when our code spans across different lines of code, and tries to keep comments around. - -What about if we _did_ introduce a type-checking error? -Let's rewrite `hello.ts`: - -```ts twoslash -// @noErrors -// This is an industrial-grade general-purpose greeter function: -function greet(person, date) { - console.log(`Hello ${person}, today is ${date}!`); -} - -greet("Brendan"); -``` - -If we run `tsc hello.ts` again, notice that we get an error on the command line! - -```txt -Expected 2 arguments, but got 1. -``` - -TypeScript is telling us we forgot to pass an argument to the `greet` function, and rightfully so. -So far we've only written standard JavaScript, and yet type-checking was still able to find problems with our code. -Thanks TypeScript! - -## Emitting with Errors - -One thing you might not have noticed from the last example was that our `hello.js` file changed again. -If we open that file up then we'll see that the contents still basically look the same as our input file. -That might be a bit surprising given the fact that `tsc` reported an error about our code, but this is based on one of TypeScript's core values: much of the time, _you_ will know better than TypeScript. - -To reiterate from earlier, type-checking code limits the sorts of programs you can run, and so there's a tradeoff on what sorts of things a type-checker finds acceptable. -Most of the time that's okay, but there are scenarios where those checks get in the way. -For example, imagine yourself migrating JavaScript code over to TypeScript and introducing type-checking errors. -Eventually you'll get around to cleaning things up for the type-checker, but that original JavaScript code was already working! -Why should converting it over to TypeScript stop you from running it? - -So TypeScript doesn't get in your way. -Of course, over time, you may want to be a bit more defensive against mistakes, and make TypeScript act a bit more strictly. -In that case, you can use the `--noEmitOnError` compiler option. -Try changing your `hello.ts` file and running `tsc` with that flag: - -```sh -tsc --noEmitOnError hello.ts -``` - -You'll notice that `hello.js` never gets updated. - -## Explicit Types - -Up until now, we haven't told TypeScript what `person` or `date` are. -Let's edit the code to tell TypeScript that `person` is a `string`, and that `date` should be a `Date` object. -We'll also use the `toDateString()` method on `date`. - -```ts twoslash -function greet(person: string, date: Date) { - console.log(`Hello ${person}, today is ${date.toDateString()}!`); -} -``` - -What we did was add _type annotations_ on `person` and `date` to describe what types of values `greet` can be called with. -You can read that signature as "`greet` takes a `person` of type `string`, and a `date` of type `Date`". - -With this, TypeScript can tell us about other cases where we might have been called incorrectly. -For example... - -```ts twoslash -// @errors: 2345 -function greet(person: string, date: Date) { - console.log(`Hello ${person}, today is ${date.toDateString()}!`); -} - -greet("Maddison", Date()); -``` - -Huh? -TypeScript reported an error on our second argument, but why? - -Perhaps surprisingly, calling `Date()` in JavaScript returns a `string`. -On the other hand, constructing a `Date` with `new Date()` actually gives us what we were expecting. - -Anyway, we can quickly fix up the error: - -```ts twoslash {4} -function greet(person: string, date: Date) { - console.log(`Hello ${person}, today is ${date.toDateString()}!`); -} - -greet("Maddison", new Date()); -``` - -Keep in mind, we don't always have to write explicit type annotations. -In many cases, TypeScript can even just _infer_ (or "figure out") the types for us even if we omit them. - -```ts twoslash -let msg = "hello there!"; -// ^? -``` - -Even though we didn't tell TypeScript that `msg` had the type `string` it was able to figure that out. -That's a feature, and it's best not to add annotations when the type system would end up inferring the same type anyway. - -> Note: the message bubble inside the code sample above. That is what your editor would show if you had hovered over the word. - -## Erased Types - -Let's take a look at what happens when we compile the above function `greet` with `tsc` to output JavaScript: - -```ts twoslash -// @showEmit -// @target: es5 -function greet(person: string, date: Date) { - console.log(`Hello ${person}, today is ${date.toDateString()}!`); -} - -greet("Maddison", new Date()); -``` - -Notice two things here: - -1. Our `person` and `date` parameters no longer have type annotations. -2. Our "template string" - that string that used backticks (the `` ` `` character) - was converted to plain strings with concatenations (`+`). - -More on that second point later, but let's now focus on that first point. -Type annotations aren't part of JavaScript (or ECMAScript to be pedantic), so there really aren't any browsers or other runtimes that can just run TypeScript unmodified. -That's why TypeScript needs a compiler in the first place - it needs some way to strip out or transform any TypeScript-specific code so that you can run it. -Most TypeScript-specific code gets erased away, and likewise, here our type annotations were completely erased. - -> **Remember**: Type annotations never change the runtime behavior of your program. - -## Downleveling - -One other difference from the above was that our template string was rewritten from - -```js -`Hello ${person}, today is ${date.toDateString()}!`; -``` - -to - -```js -"Hello " + person + ", today is " + date.toDateString() + "!"; -``` - -Why did this happen? - -Template strings are a feature from a version of ECMAScript called ECMAScript 2015 (a.k.a. ECMAScript 6, ES2015, ES6, etc. - _don't ask_). -TypeScript has the ability to rewrite code from newer versions of ECMAScript to older ones such as ECMAScript 3 or ECMAScript 5 (a.k.a. ES3 and ES5). -This process of moving from a newer or "higher" version of ECMAScript down to an older or "lower" one is sometimes called _downleveling_. - -By default TypeScript targets ES3, an extremely old version of ECMAScript. -We could have chosen something a little bit more recent by using the `--target` flag. -Running with `--target es2015` changes TypeScript to target ECMAScript 2015, meaning code should be able to run wherever ECMAScript 2015 is supported. -So running `tsc --target es2015 hello.ts` gives us the following output: - -```js -function greet(person, date) { - console.log(`Hello ${person}, today is ${date.toDateString()}!`); -} -greet("Maddison", new Date()); -``` - -> While the default target is ES3, the great majority of current browsers support ES2015. -> Most developers can therefore safely specify ES2015 or above as a target, unless compatibility with certain ancient browsers is important. - -## Strictness - -Different users come to TypeScript looking for different things in a type-checker. -Some people are looking for a more loose opt-in experience which can help validate only some parts of their program, and still have decent tooling. -This is the default experience with TypeScript, where types are optional, inference takes the most lenient types, and there's no checking for potentially `null`/`undefined` values. -Much like how `tsc` emits in the face of errors, these defaults are put in place to stay out of your way. -If you're migrating existing JavaScript, that might be a desirable first step. - -In contrast, a lot of users prefer to have TypeScript validate as much as it can straight away, and that's why the language provides strictness settings as well. -These strictness settings turn static type-checking from a switch (either your code is checked or not) into something closer to a dial. -The further you turn this dial up, the more TypeScript will check for you. -This can require a little extra work, but generally speaking it pays for itself in the long run, and enables more thorough checks and more accurate tooling. -When possible, a new codebase should always turn these strictness checks on. - -TypeScript has several type-checking strictness flags that can be turned on or off, and all of our examples will be written with all of them enabled unless otherwise stated. -The `--strict` flag in the CLI, or `"strict": true` in a [`tsconfig.json`](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) toggles them all on simultaneously, but we can opt out of them individually. -The two biggest ones you should know about are `noImplicitAny` and `strictNullChecks`. - -## `noImplicitAny` - -Recall that in some places, TypeScript doesn't try to infer any types for us and instead falls back to the most lenient type: `any`. -This isn't the worst thing that can happen - after all, falling back to `any` is just the plain JavaScript experience anyway. - -However, using `any` often defeats the purpose of using TypeScript in the first place. -The more typed your program is, the more validation and tooling you'll get, meaning you'll run into fewer bugs as you code. -Turning on the `noImplicitAny` flag will issue an error on any variables whose type is implicitly inferred as `any`. - -## `strictNullChecks` - -By default, values like `null` and `undefined` are assignable to any other type. -This can make writing some code easier, but forgetting to handle `null` and `undefined` is the cause of countless bugs in the world - some consider it a [billion dollar mistake](https://www.youtube.com/watch?v=ybrQvs4x0Ps)! -The `strictNullChecks` flag makes handling `null` and `undefined` more explicit, and _spares_ us from worrying about whether we _forgot_ to handle `null` and `undefined`. diff --git a/docs/documentation/zh/handbook-v2/Classes.md b/docs/documentation/zh/handbook-v2/Classes.md deleted file mode 100644 index 46ce7800..00000000 --- a/docs/documentation/zh/handbook-v2/Classes.md +++ /dev/null @@ -1,1414 +0,0 @@ ---- -title: Classes -layout: docs -permalink: /docs/handbook/2/classes.html -oneline: "How classes work in TypeScript" ---- - -

-

Background Reading:
Classes (MDN)

-
- -TypeScript offers full support for the `class` keyword introduced in ES2015. - -As with other JavaScript language features, TypeScript adds type annotations and other syntax to allow you to express relationships between classes and other types. - -## Class Members - -Here's the most basic class - an empty one: - -```ts twoslash -class Point {} -``` - -This class isn't very useful yet, so let's start adding some members. - -### Fields - -A field declaration creates a public writeable property on a class: - -```ts twoslash -// @strictPropertyInitialization: false -class Point { - x: number; - y: number; -} - -const pt = new Point(); -pt.x = 0; -pt.y = 0; -``` - -As with other locations, the type annotation is optional, but will be an implicit `any` if not specified. - -Fields can also have _initializers_; these will run automatically when the class is instantiated: - -```ts twoslash -class Point { - x = 0; - y = 0; -} - -const pt = new Point(); -// Prints 0, 0 -console.log(`${pt.x}, ${pt.y}`); -``` - -Just like with `const`, `let`, and `var`, the initializer of a class property will be used to infer its type: - -```ts twoslash -// @errors: 2322 -class Point { - x = 0; - y = 0; -} -// ---cut--- -const pt = new Point(); -pt.x = "0"; -``` - -#### `--strictPropertyInitialization` - -The `strictPropertyInitialization` setting controls whether class fields need to be initialized in the constructor. - -```ts twoslash -// @errors: 2564 -class BadGreeter { - name: string; -} -``` - -```ts twoslash -class GoodGreeter { - name: string; - - constructor() { - this.name = "hello"; - } -} -``` - -Note that the field needs to be initialized _in the constructor itself_. -TypeScript does not analyze methods you invoke from the constructor to detect initializations, because a derived class might override those methods and fail to initialize the members. - -If you intend to definitely initialize a field through means other than the constructor (for example, maybe an external library is filling in part of your class for you), you can use the _definite assignment assertion operator_, `!`: - -```ts twoslash -class OKGreeter { - // Not initialized, but no error - name!: string; -} -``` - -### `readonly` - -Fields may be prefixed with the `readonly` modifier. -This prevents assignments to the field outside of the constructor. - -```ts twoslash -// @errors: 2540 2540 -class Greeter { - readonly name: string = "world"; - - constructor(otherName?: string) { - if (otherName !== undefined) { - this.name = otherName; - } - } - - err() { - this.name = "not ok"; - } -} -const g = new Greeter(); -g.name = "also not ok"; -``` - -### Constructors - -
-

Background Reading:
- Constructor (MDN)
-

-
- -Class constructors are very similar to functions. -You can add parameters with type annotations, default values, and overloads: - -```ts twoslash -class Point { - x: number; - y: number; - - // Normal signature with defaults - constructor(x = 0, y = 0) { - this.x = x; - this.y = y; - } -} -``` - -```ts twoslash -class Point { - // Overloads - constructor(x: number, y: string); - constructor(s: string); - constructor(xs: any, y?: any) { - // TBD - } -} -``` - -There are just a few differences between class constructor signatures and function signatures: - -- Constructors can't have type parameters - these belong on the outer class declaration, which we'll learn about later -- Constructors can't have return type annotations - the class instance type is always what's returned - -#### Super Calls - -Just as in JavaScript, if you have a base class, you'll need to call `super();` in your constructor body before using any `this.` members: - -```ts twoslash -// @errors: 17009 -class Base { - k = 4; -} - -class Derived extends Base { - constructor() { - // Prints a wrong value in ES5; throws exception in ES6 - console.log(this.k); - super(); - } -} -``` - -Forgetting to call `super` is an easy mistake to make in JavaScript, but TypeScript will tell you when it's necessary. - -### Methods - -
-

Background Reading:
- Method definitions
-

-
- -A function property on a class is called a _method_. -Methods can use all the same type annotations as functions and constructors: - -```ts twoslash -class Point { - x = 10; - y = 10; - - scale(n: number): void { - this.x *= n; - this.y *= n; - } -} -``` - -Other than the standard type annotations, TypeScript doesn't add anything else new to methods. - -Note that inside a method body, it is still mandatory to access fields and other methods via `this.`. -An unqualified name in a method body will always refer to something in the enclosing scope: - -```ts twoslash -// @errors: 2322 -let x: number = 0; - -class C { - x: string = "hello"; - - m() { - // This is trying to modify 'x' from line 1, not the class property - x = "world"; - } -} -``` - -### Getters / Setters - -Classes can also have _accessors_: - -```ts twoslash -class C { - _length = 0; - get length() { - return this._length; - } - set length(value) { - this._length = value; - } -} -``` - -> Note that a field-backed get/set pair with no extra logic is very rarely useful in JavaScript. -> It's fine to expose public fields if you don't need to add additional logic during the get/set operations. - -TypeScript has some special inference rules for accessors: - -- If `get` exists but no `set`, the property is automatically `readonly` -- If the type of the setter parameter is not specified, it is inferred from the return type of the getter -- Getters and setters must have the same [Member Visibility](#member-visibility) - -Since [TypeScript 4.3](https://devblogs.microsoft.com/typescript/announcing-typescript-4-3/), it is possible to have accessors with different types for getting and setting. - -```ts twoslash -class Thing { - _size = 0; - - get size(): number { - return this._size; - } - - set size(value: string | number | boolean) { - let num = Number(value); - - // Don't allow NaN, Infinity, etc - - if (!Number.isFinite(num)) { - this._size = 0; - return; - } - - this._size = num; - } -} -``` - -### Index Signatures - -Classes can declare index signatures; these work the same as [Index Signatures for other object types](/docs/handbook/2/objects.html#index-signatures): - -```ts twoslash -class MyClass { - [s: string]: boolean | ((s: string) => boolean); - - check(s: string) { - return this[s] as boolean; - } -} -``` - -Because the index signature type needs to also capture the types of methods, it's not easy to usefully use these types. -Generally it's better to store indexed data in another place instead of on the class instance itself. - -## Class Heritage - -Like other languages with object-oriented features, classes in JavaScript can inherit from base classes. - -### `implements` Clauses - -You can use an `implements` clause to check that a class satisfies a particular `interface`. -An error will be issued if a class fails to correctly implement it: - -```ts twoslash -// @errors: 2420 -interface Pingable { - ping(): void; -} - -class Sonar implements Pingable { - ping() { - console.log("ping!"); - } -} - -class Ball implements Pingable { - pong() { - console.log("pong!"); - } -} -``` - -Classes may also implement multiple interfaces, e.g. `class C implements A, B {`. - -#### Cautions - -It's important to understand that an `implements` clause is only a check that the class can be treated as the interface type. -It doesn't change the type of the class or its methods _at all_. -A common source of error is to assume that an `implements` clause will change the class type - it doesn't! - -```ts twoslash -// @errors: 7006 -interface Checkable { - check(name: string): boolean; -} - -class NameChecker implements Checkable { - check(s) { - // Notice no error here - return s.toLowercse() === "ok"; - // ^? - } -} -``` - -In this example, we perhaps expected that `s`'s type would be influenced by the `name: string` parameter of `check`. -It is not - `implements` clauses don't change how the class body is checked or its type inferred. - -Similarly, implementing an interface with an optional property doesn't create that property: - -```ts twoslash -// @errors: 2339 -interface A { - x: number; - y?: number; -} -class C implements A { - x = 0; -} -const c = new C(); -c.y = 10; -``` - -### `extends` Clauses - -
-

Background Reading:
- extends keyword (MDN)
-

-
- -Classes may `extend` from a base class. -A derived class has all the properties and methods of its base class, and also define additional members. - -```ts twoslash -class Animal { - move() { - console.log("Moving along!"); - } -} - -class Dog extends Animal { - woof(times: number) { - for (let i = 0; i < times; i++) { - console.log("woof!"); - } - } -} - -const d = new Dog(); -// Base class method -d.move(); -// Derived class method -d.woof(3); -``` - -#### Overriding Methods - -
-

Background Reading:
- super keyword (MDN)
-

-
- -A derived class can also override a base class field or property. -You can use the `super.` syntax to access base class methods. -Note that because JavaScript classes are a simple lookup object, there is no notion of a "super field". - -TypeScript enforces that a derived class is always a subtype of its base class. - -For example, here's a legal way to override a method: - -```ts twoslash -class Base { - greet() { - console.log("Hello, world!"); - } -} - -class Derived extends Base { - greet(name?: string) { - if (name === undefined) { - super.greet(); - } else { - console.log(`Hello, ${name.toUpperCase()}`); - } - } -} - -const d = new Derived(); -d.greet(); -d.greet("reader"); -``` - -It's important that a derived class follow its base class contract. -Remember that it's very common (and always legal!) to refer to a derived class instance through a base class reference: - -```ts twoslash -class Base { - greet() { - console.log("Hello, world!"); - } -} -declare const d: Base; -// ---cut--- -// Alias the derived instance through a base class reference -const b: Base = d; -// No problem -b.greet(); -``` - -What if `Derived` didn't follow `Base`'s contract? - -```ts twoslash -// @errors: 2416 -class Base { - greet() { - console.log("Hello, world!"); - } -} - -class Derived extends Base { - // Make this parameter required - greet(name: string) { - console.log(`Hello, ${name.toUpperCase()}`); - } -} -``` - -If we compiled this code despite the error, this sample would then crash: - -```ts twoslash -declare class Base { - greet(): void; -} -declare class Derived extends Base {} -// ---cut--- -const b: Base = new Derived(); -// Crashes because "name" will be undefined -b.greet(); -``` - -#### Initialization Order - -The order that JavaScript classes initialize can be surprising in some cases. -Let's consider this code: - -```ts twoslash -class Base { - name = "base"; - constructor() { - console.log("My name is " + this.name); - } -} - -class Derived extends Base { - name = "derived"; -} - -// Prints "base", not "derived" -const d = new Derived(); -``` - -What happened here? - -The order of class initialization, as defined by JavaScript, is: - -- The base class fields are initialized -- The base class constructor runs -- The derived class fields are initialized -- The derived class constructor runs - -This means that the base class constructor saw its own value for `name` during its own constructor, because the derived class field initializations hadn't run yet. - -#### Inheriting Built-in Types - -> Note: If you don't plan to inherit from built-in types like `Array`, `Error`, `Map`, etc. or your compilation target is explicitely set to `ES6`/`ES2015` or above, you may skip this section - -In ES2015, constructors which return an object implicitly substitute the value of `this` for any callers of `super(...)`. -It is necessary for generated constructor code to capture any potential return value of `super(...)` and replace it with `this`. - -As a result, subclassing `Error`, `Array`, and others may no longer work as expected. -This is due to the fact that constructor functions for `Error`, `Array`, and the like use ECMAScript 6's `new.target` to adjust the prototype chain; -however, there is no way to ensure a value for `new.target` when invoking a constructor in ECMAScript 5. -Other downlevel compilers generally have the same limitation by default. - -For a subclass like the following: - -```ts twoslash -class MsgError extends Error { - constructor(m: string) { - super(m); - } - sayHello() { - return "hello " + this.message; - } -} -``` - -you may find that: - -- methods may be `undefined` on objects returned by constructing these subclasses, so calling `sayHello` will result in an error. -- `instanceof` will be broken between instances of the subclass and their instances, so `(new MsgError()) instanceof MsgError` will return `false`. - -As a recommendation, you can manually adjust the prototype immediately after any `super(...)` calls. - -```ts twoslash -class MsgError extends Error { - constructor(m: string) { - super(m); - - // Set the prototype explicitly. - Object.setPrototypeOf(this, MsgError.prototype); - } - - sayHello() { - return "hello " + this.message; - } -} -``` - -However, any subclass of `MsgError` will have to manually set the prototype as well. -For runtimes that don't support [`Object.setPrototypeOf`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf), you may instead be able to use [`__proto__`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto). - -Unfortunately, [these workarounds will not work on Internet Explorer 10 and prior](). -One can manually copy methods from the prototype onto the instance itself (i.e. `MsgError.prototype` onto `this`), but the prototype chain itself cannot be fixed. - -## Member Visibility - -You can use TypeScript to control whether certain methods or properties are visible to code outside the class. - -### `public` - -The default visibility of class members is `public`. -A `public` member can be accessed anywhere: - -```ts twoslash -class Greeter { - public greet() { - console.log("hi!"); - } -} -const g = new Greeter(); -g.greet(); -``` - -Because `public` is already the default visibility modifier, you don't ever _need_ to write it on a class member, but might choose to do so for style/readability reasons. - -### `protected` - -`protected` members are only visible to subclasses of the class they're declared in. - -```ts twoslash -// @errors: 2445 -class Greeter { - public greet() { - console.log("Hello, " + this.getName()); - } - protected getName() { - return "hi"; - } -} - -class SpecialGreeter extends Greeter { - public howdy() { - // OK to access protected member here - console.log("Howdy, " + this.getName()); - // ^^^^^^^^^^^^^^ - } -} -const g = new SpecialGreeter(); -g.greet(); // OK -g.getName(); -``` - -#### Exposure of `protected` members - -Derived classes need to follow their base class contracts, but may choose to expose a subtype of base class with more capabilities. -This includes making `protected` members `public`: - -```ts twoslash -class Base { - protected m = 10; -} -class Derived extends Base { - // No modifier, so default is 'public' - m = 15; -} -const d = new Derived(); -console.log(d.m); // OK -``` - -Note that `Derived` was already able to freely read and write `m`, so this doesn't meaningfully alter the "security" of this situation. -The main thing to note here is that in the derived class, we need to be careful to repeat the `protected` modifier if this exposure isn't intentional. - -#### Cross-hierarchy `protected` access - -Different OOP languages disagree about whether it's legal to access a `protected` member through a base class reference: - -```ts twoslash -// @errors: 2446 -class Base { - protected x: number = 1; -} -class Derived1 extends Base { - protected x: number = 5; -} -class Derived2 extends Base { - f1(other: Derived2) { - other.x = 10; - } - f2(other: Base) { - other.x = 10; - } -} -``` - -Java, for example, considers this to be legal. -On the other hand, C# and C++ chose that this code should be illegal. - -TypeScript sides with C# and C++ here, because accessing `x` in `Derived2` should only be legal from `Derived2`'s subclasses, and `Derived1` isn't one of them. -Moreover, if accessing `x` through a `Derived1` reference is illegal (which it certainly should be!), then accessing it through a base class reference should never improve the situation. - -See also [Why Can’t I Access A Protected Member From A Derived Class?](https://blogs.msdn.microsoft.com/ericlippert/2005/11/09/why-cant-i-access-a-protected-member-from-a-derived-class/) which explains more of C#'s reasoning. - -### `private` - -`private` is like `protected`, but doesn't allow access to the member even from subclasses: - -```ts twoslash -// @errors: 2341 -class Base { - private x = 0; -} -const b = new Base(); -// Can't access from outside the class -console.log(b.x); -``` - -```ts twoslash -// @errors: 2341 -class Base { - private x = 0; -} -// ---cut--- -class Derived extends Base { - showX() { - // Can't access in subclasses - console.log(this.x); - } -} -``` - -Because `private` members aren't visible to derived classes, a derived class can't increase its visibility: - -```ts twoslash -// @errors: 2415 -class Base { - private x = 0; -} -class Derived extends Base { - x = 1; -} -``` - -#### Cross-instance `private` access - -Different OOP languages disagree about whether different instances of the same class may access each others' `private` members. -While languages like Java, C#, C++, Swift, and PHP allow this, Ruby does not. - -TypeScript does allow cross-instance `private` access: - -```ts twoslash -class A { - private x = 10; - - public sameAs(other: A) { - // No error - return other.x === this.x; - } -} -``` - -#### Caveats - -Like other aspects of TypeScript's type system, `private` and `protected` [are only enforced during type checking](https://www.typescriptlang.org/play?removeComments=true&target=99&ts=4.3.4#code/PTAEGMBsEMGddAEQPYHNQBMCmVoCcsEAHPASwDdoAXLUAM1K0gwQFdZSA7dAKWkoDK4MkSoByBAGJQJLAwAeAWABQIUH0HDSoiTLKUaoUggAW+DHorUsAOlABJcQlhUy4KpACeoLJzrI8cCwMGxU1ABVPIiwhESpMZEJQTmR4lxFQaQxWMm4IZABbIlIYKlJkTlDlXHgkNFAAbxVQTIAjfABrAEEC5FZOeIBeUAAGAG5mmSw8WAroSFIqb2GAIjMiIk8VieVJ8Ar01ncAgAoASkaAXxVr3dUwGoQAYWpMHBgCYn1rekZmNg4eUi0Vi2icoBWJCsNBWoA6WE8AHcAiEwmBgTEtDovtDaMZQLM6PEoQZbA5wSk0q5SO4vD4-AEghZoJwLGYEIRwNBoqAzFRwCZCFUIlFMXECdSiAhId8YZgclx0PsiiVqOVOAAaUAFLAsxWgKiC35MFigfC0FKgSAVVDTSyk+W5dB4fplHVVR6gF7xJrKFotEk-HXIRE9PoDUDDcaTAPTWaceaLZYQlmoPBbHYx-KcQ7HPDnK43FQqfY5+IMDDISPJLCIuqoc47UsuUCofAME3Vzi1r3URvF5QV5A2STtPDdXqunZDgDaYlHnTDrrEAF0dm28B3mDZg6HJwN1+2-hg57ulwNV2NQGoZbjYfNrYiENBwEFaojFiZQK08C-4fFKTVCozWfTgfFgLkeT5AUqiAA). - -This means that JavaScript runtime constructs like `in` or simple property lookup can still access a `private` or `protected` member: - -```ts twoslash -class MySafe { - private secretKey = 12345; -} -``` - -```js -// In a JavaScript file... -const s = new MySafe(); -// Will print 12345 -console.log(s.secretKey); -``` - -`private` also allows access using bracket notation during type checking. This makes `private`-declared fields potentially easier to access for things like unit tests, with the drawback that these fields are _soft private_ and don't strictly enforce privacy. - -```ts twoslash -// @errors: 2341 -class MySafe { - private secretKey = 12345; -} - -const s = new MySafe(); - -// Not allowed during type checking -console.log(s.secretKey); - -// OK -console.log(s["secretKey"]); -``` - -Unlike TypeScripts's `private`, JavaScript's [private fields](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields) (`#`) remain private after compilation and do not provide the previously mentioned escape hatches like bracket notation access, making them _hard private_. - -```ts twoslash -class Dog { - #barkAmount = 0; - personality = "happy"; - - constructor() {} -} -``` - -```ts twoslash -// @target: esnext -// @showEmit -class Dog { - #barkAmount = 0; - personality = "happy"; - - constructor() {} -} -``` - -When compiling to ES2021 or less, TypeScript will use WeakMaps in place of `#`. - -```ts twoslash -// @target: es2015 -// @showEmit -class Dog { - #barkAmount = 0; - personality = "happy"; - - constructor() {} -} -``` - -If you need to protect values in your class from malicious actors, you should use mechanisms that offer hard runtime privacy, such as closures, WeakMaps, or private fields. Note that these added privacy checks during runtime could affect performance. - -## Static Members - -
-

Background Reading:
- Static Members (MDN)
-

-
- -Classes may have `static` members. -These members aren't associated with a particular instance of the class. -They can be accessed through the class constructor object itself: - -```ts twoslash -class MyClass { - static x = 0; - static printX() { - console.log(MyClass.x); - } -} -console.log(MyClass.x); -MyClass.printX(); -``` - -Static members can also use the same `public`, `protected`, and `private` visibility modifiers: - -```ts twoslash -// @errors: 2341 -class MyClass { - private static x = 0; -} -console.log(MyClass.x); -``` - -Static members are also inherited: - -```ts twoslash -class Base { - static getGreeting() { - return "Hello world"; - } -} -class Derived extends Base { - myGreeting = Derived.getGreeting(); -} -``` - -### Special Static Names - -It's generally not safe/possible to overwrite properties from the `Function` prototype. -Because classes are themselves functions that can be invoked with `new`, certain `static` names can't be used. -Function properties like `name`, `length`, and `call` aren't valid to define as `static` members: - -```ts twoslash -// @errors: 2699 -class S { - static name = "S!"; -} -``` - -### Why No Static Classes? - -TypeScript (and JavaScript) don't have a construct called `static class` the same way C# and Java do. - -Those constructs _only_ exist because those languages force all data and functions to be inside a class; because that restriction doesn't exist in TypeScript, there's no need for them. -A class with only a single instance is typically just represented as a normal _object_ in JavaScript/TypeScript. - -For example, we don't need a "static class" syntax in TypeScript because a regular object (or even top-level function) will do the job just as well: - -```ts twoslash -// Unnecessary "static" class -class MyStaticClass { - static doSomething() {} -} - -// Preferred (alternative 1) -function doSomething() {} - -// Preferred (alternative 2) -const MyHelperObject = { - dosomething() {}, -}; -``` - -## `static` Blocks in Classes - -Static blocks allow you to write a sequence of statements with their own scope that can access private fields within the containing class. This means that we can write initialization code with all the capabilities of writing statements, no leakage of variables, and full access to our class's internals. - -```ts twoslash -declare function loadLastInstances(): any[] -// ---cut--- -class Foo { - static #count = 0; - - get count() { - return Foo.#count; - } - - static { - try { - const lastInstances = loadLastInstances(); - Foo.#count += lastInstances.length; - } - catch {} - } -} -``` - -## Generic Classes - -Classes, much like interfaces, can be generic. -When a generic class is instantiated with `new`, its type parameters are inferred the same way as in a function call: - -```ts twoslash -class Box { - contents: Type; - constructor(value: Type) { - this.contents = value; - } -} - -const b = new Box("hello!"); -// ^? -``` - -Classes can use generic constraints and defaults the same way as interfaces. - -### Type Parameters in Static Members - -This code isn't legal, and it may not be obvious why: - -```ts twoslash -// @errors: 2302 -class Box { - static defaultValue: Type; -} -``` - -Remember that types are always fully erased! -At runtime, there's only _one_ `Box.defaultValue` property slot. -This means that setting `Box.defaultValue` (if that were possible) would _also_ change `Box.defaultValue` - not good. -The `static` members of a generic class can never refer to the class's type parameters. - -## `this` at Runtime in Classes - -
-

Background Reading:
- this keyword (MDN)
-

-
- -It's important to remember that TypeScript doesn't change the runtime behavior of JavaScript, and that JavaScript is somewhat famous for having some peculiar runtime behaviors. - -JavaScript's handling of `this` is indeed unusual: - -```ts twoslash -class MyClass { - name = "MyClass"; - getName() { - return this.name; - } -} -const c = new MyClass(); -const obj = { - name: "obj", - getName: c.getName, -}; - -// Prints "obj", not "MyClass" -console.log(obj.getName()); -``` - -Long story short, by default, the value of `this` inside a function depends on _how the function was called_. -In this example, because the function was called through the `obj` reference, its value of `this` was `obj` rather than the class instance. - -This is rarely what you want to happen! -TypeScript provides some ways to mitigate or prevent this kind of error. - -### Arrow Functions - -
-

Background Reading:
- Arrow functions (MDN)
-

-
- -If you have a function that will often be called in a way that loses its `this` context, it can make sense to use an arrow function property instead of a method definition: - -```ts twoslash -class MyClass { - name = "MyClass"; - getName = () => { - return this.name; - }; -} -const c = new MyClass(); -const g = c.getName; -// Prints "MyClass" instead of crashing -console.log(g()); -``` - -This has some trade-offs: - -- The `this` value is guaranteed to be correct at runtime, even for code not checked with TypeScript -- This will use more memory, because each class instance will have its own copy of each function defined this way -- You can't use `super.getName` in a derived class, because there's no entry in the prototype chain to fetch the base class method from - -### `this` parameters - -In a method or function definition, an initial parameter named `this` has special meaning in TypeScript. -These parameters are erased during compilation: - -```ts twoslash -type SomeType = any; -// ---cut--- -// TypeScript input with 'this' parameter -function fn(this: SomeType, x: number) { - /* ... */ -} -``` - -```js -// JavaScript output -function fn(x) { - /* ... */ -} -``` - -TypeScript checks that calling a function with a `this` parameter is done so with a correct context. -Instead of using an arrow function, we can add a `this` parameter to method definitions to statically enforce that the method is called correctly: - -```ts twoslash -// @errors: 2684 -class MyClass { - name = "MyClass"; - getName(this: MyClass) { - return this.name; - } -} -const c = new MyClass(); -// OK -c.getName(); - -// Error, would crash -const g = c.getName; -console.log(g()); -``` - -This method takes the opposite trade-offs of the arrow function approach: - -- JavaScript callers might still use the class method incorrectly without realizing it -- Only one function per class definition gets allocated, rather than one per class instance -- Base method definitions can still be called via `super.` - -## `this` Types - -In classes, a special type called `this` refers _dynamically_ to the type of the current class. -Let's see how this is useful: - - -```ts twoslash -class Box { - contents: string = ""; - set(value: string) { -// ^? - this.contents = value; - return this; - } -} -``` - -Here, TypeScript inferred the return type of `set` to be `this`, rather than `Box`. -Now let's make a subclass of `Box`: - -```ts twoslash -class Box { - contents: string = ""; - set(value: string) { - this.contents = value; - return this; - } -} -// ---cut--- -class ClearableBox extends Box { - clear() { - this.contents = ""; - } -} - -const a = new ClearableBox(); -const b = a.set("hello"); -// ^? -``` - -You can also use `this` in a parameter type annotation: - -```ts twoslash -class Box { - content: string = ""; - sameAs(other: this) { - return other.content === this.content; - } -} -``` - -This is different from writing `other: Box` -- if you have a derived class, its `sameAs` method will now only accept other instances of that same derived class: - -```ts twoslash -// @errors: 2345 -class Box { - content: string = ""; - sameAs(other: this) { - return other.content === this.content; - } -} - -class DerivedBox extends Box { - otherContent: string = "?"; -} - -const base = new Box(); -const derived = new DerivedBox(); -derived.sameAs(base); -``` - -### `this`-based type guards - -You can use `this is Type` in the return position for methods in classes and interfaces. -When mixed with a type narrowing (e.g. `if` statements) the type of the target object would be narrowed to the specified `Type`. - - -```ts twoslash -// @strictPropertyInitialization: false -class FileSystemObject { - isFile(): this is FileRep { - return this instanceof FileRep; - } - isDirectory(): this is Directory { - return this instanceof Directory; - } - isNetworked(): this is Networked & this { - return this.networked; - } - constructor(public path: string, private networked: boolean) {} -} - -class FileRep extends FileSystemObject { - constructor(path: string, public content: string) { - super(path, false); - } -} - -class Directory extends FileSystemObject { - children: FileSystemObject[]; -} - -interface Networked { - host: string; -} - -const fso: FileSystemObject = new FileRep("foo/bar.txt", "foo"); - -if (fso.isFile()) { - fso.content; -// ^? -} else if (fso.isDirectory()) { - fso.children; -// ^? -} else if (fso.isNetworked()) { - fso.host; -// ^? -} -``` - -A common use-case for a this-based type guard is to allow for lazy validation of a particular field. For example, this case removes an `undefined` from the value held inside box when `hasValue` has been verified to be true: - -```ts twoslash -class Box { - value?: T; - - hasValue(): this is { value: T } { - return this.value !== undefined; - } -} - -const box = new Box(); -box.value = "Gameboy"; - -box.value; -// ^? - -if (box.hasValue()) { - box.value; - // ^? -} -``` - -## Parameter Properties - -TypeScript offers special syntax for turning a constructor parameter into a class property with the same name and value. -These are called _parameter properties_ and are created by prefixing a constructor argument with one of the visibility modifiers `public`, `private`, `protected`, or `readonly`. -The resulting field gets those modifier(s): - -```ts twoslash -// @errors: 2341 -class Params { - constructor( - public readonly x: number, - protected y: number, - private z: number - ) { - // No body necessary - } -} -const a = new Params(1, 2, 3); -console.log(a.x); -// ^? -console.log(a.z); -``` - -## Class Expressions - -
-

Background Reading:
- Class expressions (MDN)
-

-
- -Class expressions are very similar to class declarations. -The only real difference is that class expressions don't need a name, though we can refer to them via whatever identifier they ended up bound to: - -```ts twoslash -const someClass = class { - content: Type; - constructor(value: Type) { - this.content = value; - } -}; - -const m = new someClass("Hello, world"); -// ^? -``` - -## `abstract` Classes and Members - -Classes, methods, and fields in TypeScript may be _abstract_. - -An _abstract method_ or _abstract field_ is one that hasn't had an implementation provided. -These members must exist inside an _abstract class_, which cannot be directly instantiated. - -The role of abstract classes is to serve as a base class for subclasses which do implement all the abstract members. -When a class doesn't have any abstract members, it is said to be _concrete_. - -Let's look at an example - -```ts twoslash -// @errors: 2511 -abstract class Base { - abstract getName(): string; - - printName() { - console.log("Hello, " + this.getName()); - } -} - -const b = new Base(); -``` - -We can't instantiate `Base` with `new` because it's abstract. -Instead, we need to make a derived class and implement the abstract members: - -```ts twoslash -abstract class Base { - abstract getName(): string; - printName() {} -} -// ---cut--- -class Derived extends Base { - getName() { - return "world"; - } -} - -const d = new Derived(); -d.printName(); -``` - -Notice that if we forget to implement the base class's abstract members, we'll get an error: - -```ts twoslash -// @errors: 2515 -abstract class Base { - abstract getName(): string; - printName() {} -} -// ---cut--- -class Derived extends Base { - // forgot to do anything -} -``` - -### Abstract Construct Signatures - -Sometimes you want to accept some class constructor function that produces an instance of a class which derives from some abstract class. - -For example, you might want to write this code: - -```ts twoslash -// @errors: 2511 -abstract class Base { - abstract getName(): string; - printName() {} -} -class Derived extends Base { - getName() { - return ""; - } -} -// ---cut--- -function greet(ctor: typeof Base) { - const instance = new ctor(); - instance.printName(); -} -``` - -TypeScript is correctly telling you that you're trying to instantiate an abstract class. -After all, given the definition of `greet`, it's perfectly legal to write this code, which would end up constructing an abstract class: - -```ts twoslash -declare const greet: any, Base: any; -// ---cut--- -// Bad! -greet(Base); -``` - -Instead, you want to write a function that accepts something with a construct signature: - -```ts twoslash -// @errors: 2345 -abstract class Base { - abstract getName(): string; - printName() {} -} -class Derived extends Base { - getName() { - return ""; - } -} -// ---cut--- -function greet(ctor: new () => Base) { - const instance = new ctor(); - instance.printName(); -} -greet(Derived); -greet(Base); -``` - -Now TypeScript correctly tells you about which class constructor functions can be invoked - `Derived` can because it's concrete, but `Base` cannot. - -## Relationships Between Classes - -In most cases, classes in TypeScript are compared structurally, the same as other types. - -For example, these two classes can be used in place of each other because they're identical: - -```ts twoslash -class Point1 { - x = 0; - y = 0; -} - -class Point2 { - x = 0; - y = 0; -} - -// OK -const p: Point1 = new Point2(); -``` - -Similarly, subtype relationships between classes exist even if there's no explicit inheritance: - -```ts twoslash -// @strict: false -class Person { - name: string; - age: number; -} - -class Employee { - name: string; - age: number; - salary: number; -} - -// OK -const p: Person = new Employee(); -``` - -This sounds straightforward, but there are a few cases that seem stranger than others. - -Empty classes have no members. -In a structural type system, a type with no members is generally a supertype of anything else. -So if you write an empty class (don't!), anything can be used in place of it: - -```ts twoslash -class Empty {} - -function fn(x: Empty) { - // can't do anything with 'x', so I won't -} - -// All OK! -fn(window); -fn({}); -fn(fn); -``` diff --git a/docs/documentation/zh/handbook-v2/Everyday Types.md b/docs/documentation/zh/handbook-v2/Everyday Types.md deleted file mode 100644 index 29f3201b..00000000 --- a/docs/documentation/zh/handbook-v2/Everyday Types.md +++ /dev/null @@ -1,714 +0,0 @@ ---- -title: Everyday Types -layout: docs -permalink: /docs/handbook/2/everyday-types.html -oneline: "The language primitives." ---- - -In this chapter, we'll cover some of the most common types of values you'll find in JavaScript code, and explain the corresponding ways to describe those types in TypeScript. -This isn't an exhaustive list, and future chapters will describe more ways to name and use other types. - -Types can also appear in many more _places_ than just type annotations. -As we learn about the types themselves, we'll also learn about the places where we can refer to these types to form new constructs. - -We'll start by reviewing the most basic and common types you might encounter when writing JavaScript or TypeScript code. -These will later form the core building blocks of more complex types. - -## The primitives: `string`, `number`, and `boolean` - -JavaScript has three very commonly used [primitives](https://developer.mozilla.org/en-US/docs/Glossary/Primitive): `string`, `number`, and `boolean`. -Each has a corresponding type in TypeScript. -As you might expect, these are the same names you'd see if you used the JavaScript `typeof` operator on a value of those types: - -- `string` represents string values like `"Hello, world"` -- `number` is for numbers like `42`. JavaScript does not have a special runtime value for integers, so there's no equivalent to `int` or `float` - everything is simply `number` -- `boolean` is for the two values `true` and `false` - -> The type names `String`, `Number`, and `Boolean` (starting with capital letters) are legal, but refer to some special built-in types that will very rarely appear in your code. _Always_ use `string`, `number`, or `boolean` for types. - -## Arrays - -To specify the type of an array like `[1, 2, 3]`, you can use the syntax `number[]`; this syntax works for any type (e.g. `string[]` is an array of strings, and so on). -You may also see this written as `Array`, which means the same thing. -We'll learn more about the syntax `T` when we cover _generics_. - -> Note that `[number]` is a different thing; refer to the section on [Tuples](/docs/handbook/2/objects.html#tuple-types). - - -## `any` - -TypeScript also has a special type, `any`, that you can use whenever you don't want a particular value to cause typechecking errors. - -When a value is of type `any`, you can access any properties of it (which will in turn be of type `any`), call it like a function, assign it to (or from) a value of any type, or pretty much anything else that's syntactically legal: - -```ts twoslash -let obj: any = { x: 0 }; -// None of the following lines of code will throw compiler errors. -// Using `any` disables all further type checking, and it is assumed -// you know the environment better than TypeScript. -obj.foo(); -obj(); -obj.bar = 100; -obj = "hello"; -const n: number = obj; -``` - -The `any` type is useful when you don't want to write out a long type just to convince TypeScript that a particular line of code is okay. - -### `noImplicitAny` - -When you don't specify a type, and TypeScript can't infer it from context, the compiler will typically default to `any`. - -You usually want to avoid this, though, because `any` isn't type-checked. -Use the compiler flag [`noImplicitAny`](/tsconfig#noImplicitAny) to flag any implicit `any` as an error. - -## Type Annotations on Variables - -When you declare a variable using `const`, `var`, or `let`, you can optionally add a type annotation to explicitly specify the type of the variable: - -```ts twoslash -let myName: string = "Alice"; -// ^^^^^^^^ Type annotation -``` - -> TypeScript doesn't use "types on the left"-style declarations like `int x = 0;` -> Type annotations will always go _after_ the thing being typed. - -In most cases, though, this isn't needed. -Wherever possible, TypeScript tries to automatically _infer_ the types in your code. -For example, the type of a variable is inferred based on the type of its initializer: - -```ts twoslash -// No type annotation needed -- 'myName' inferred as type 'string' -let myName = "Alice"; -``` - -For the most part you don't need to explicitly learn the rules of inference. -If you're starting out, try using fewer type annotations than you think - you might be surprised how few you need for TypeScript to fully understand what's going on. - -## Functions - -Functions are the primary means of passing data around in JavaScript. -TypeScript allows you to specify the types of both the input and output values of functions. - -### Parameter Type Annotations - -When you declare a function, you can add type annotations after each parameter to declare what types of parameters the function accepts. -Parameter type annotations go after the parameter name: - -```ts twoslash -// Parameter type annotation -function greet(name: string) { - // ^^^^^^^^ - console.log("Hello, " + name.toUpperCase() + "!!"); -} -``` - -When a parameter has a type annotation, arguments to that function will be checked: - -```ts twoslash -// @errors: 2345 -declare function greet(name: string): void; -// ---cut--- -// Would be a runtime error if executed! -greet(42); -``` - -> Even if you don't have type annotations on your parameters, TypeScript will still check that you passed the right number of arguments. - -### Return Type Annotations - -You can also add return type annotations. -Return type annotations appear after the parameter list: - -```ts twoslash -function getFavoriteNumber(): number { - // ^^^^^^^^ - return 26; -} -``` - -Much like variable type annotations, you usually don't need a return type annotation because TypeScript will infer the function's return type based on its `return` statements. -The type annotation in the above example doesn't change anything. -Some codebases will explicitly specify a return type for documentation purposes, to prevent accidental changes, or just for personal preference. - -### Anonymous Functions - -Anonymous functions are a little bit different from function declarations. -When a function appears in a place where TypeScript can determine how it's going to be called, the parameters of that function are automatically given types. - -Here's an example: - -```ts twoslash -// @errors: 2551 -// No type annotations here, but TypeScript can spot the bug -const names = ["Alice", "Bob", "Eve"]; - -// Contextual typing for function -names.forEach(function (s) { - console.log(s.toUppercase()); -}); - -// Contextual typing also applies to arrow functions -names.forEach((s) => { - console.log(s.toUppercase()); -}); -``` - -Even though the parameter `s` didn't have a type annotation, TypeScript used the types of the `forEach` function, along with the inferred type of the array, to determine the type `s` will have. - -This process is called _contextual typing_ because the _context_ that the function occurred within informs what type it should have. - -Similar to the inference rules, you don't need to explicitly learn how this happens, but understanding that it _does_ happen can help you notice when type annotations aren't needed. -Later, we'll see more examples of how the context that a value occurs in can affect its type. - -## Object Types - -Apart from primitives, the most common sort of type you'll encounter is an _object type_. -This refers to any JavaScript value with properties, which is almost all of them! -To define an object type, we simply list its properties and their types. - -For example, here's a function that takes a point-like object: - -```ts twoslash -// The parameter's type annotation is an object type -function printCoord(pt: { x: number; y: number }) { - // ^^^^^^^^^^^^^^^^^^^^^^^^ - console.log("The coordinate's x value is " + pt.x); - console.log("The coordinate's y value is " + pt.y); -} -printCoord({ x: 3, y: 7 }); -``` - -Here, we annotated the parameter with a type with two properties - `x` and `y` - which are both of type `number`. -You can use `,` or `;` to separate the properties, and the last separator is optional either way. - -The type part of each property is also optional. -If you don't specify a type, it will be assumed to be `any`. - -### Optional Properties - -Object types can also specify that some or all of their properties are _optional_. -To do this, add a `?` after the property name: - -```ts twoslash -function printName(obj: { first: string; last?: string }) { - // ... -} -// Both OK -printName({ first: "Bob" }); -printName({ first: "Alice", last: "Alisson" }); -``` - -In JavaScript, if you access a property that doesn't exist, you'll get the value `undefined` rather than a runtime error. -Because of this, when you _read_ from an optional property, you'll have to check for `undefined` before using it. - -```ts twoslash -// @errors: 2532 -function printName(obj: { first: string; last?: string }) { - // Error - might crash if 'obj.last' wasn't provided! - console.log(obj.last.toUpperCase()); - if (obj.last !== undefined) { - // OK - console.log(obj.last.toUpperCase()); - } - - // A safe alternative using modern JavaScript syntax: - console.log(obj.last?.toUpperCase()); -} -``` - -## Union Types - -TypeScript's type system allows you to build new types out of existing ones using a large variety of operators. -Now that we know how to write a few types, it's time to start _combining_ them in interesting ways. - -### Defining a Union Type - -The first way to combine types you might see is a _union_ type. -A union type is a type formed from two or more other types, representing values that may be _any one_ of those types. -We refer to each of these types as the union's _members_. - -Let's write a function that can operate on strings or numbers: - -```ts twoslash -// @errors: 2345 -function printId(id: number | string) { - console.log("Your ID is: " + id); -} -// OK -printId(101); -// OK -printId("202"); -// Error -printId({ myID: 22342 }); -``` - -### Working with Union Types - -It's easy to _provide_ a value matching a union type - simply provide a type matching any of the union's members. -If you _have_ a value of a union type, how do you work with it? - -TypeScript will only allow you to do things with the union if that thing is valid for _every_ member of the union. -For example, if you have the union `string | number`, you can't use methods that are only available on `string`: - -```ts twoslash -// @errors: 2339 -function printId(id: number | string) { - console.log(id.toUpperCase()); -} -``` - -The solution is to _narrow_ the union with code, the same as you would in JavaScript without type annotations. -_Narrowing_ occurs when TypeScript can deduce a more specific type for a value based on the structure of the code. - -For example, TypeScript knows that only a `string` value will have a `typeof` value `"string"`: - -```ts twoslash -function printId(id: number | string) { - if (typeof id === "string") { - // In this branch, id is of type 'string' - console.log(id.toUpperCase()); - } else { - // Here, id is of type 'number' - console.log(id); - } -} -``` - -Another example is to use a function like `Array.isArray`: - -```ts twoslash -function welcomePeople(x: string[] | string) { - if (Array.isArray(x)) { - // Here: 'x' is 'string[]' - console.log("Hello, " + x.join(" and ")); - } else { - // Here: 'x' is 'string' - console.log("Welcome lone traveler " + x); - } -} -``` - -Notice that in the `else` branch, we don't need to do anything special - if `x` wasn't a `string[]`, then it must have been a `string`. - -Sometimes you'll have a union where all the members have something in common. -For example, both arrays and strings have a `slice` method. -If every member in a union has a property in common, you can use that property without narrowing: - -```ts twoslash -// Return type is inferred as number[] | string -function getFirstThree(x: number[] | string) { - return x.slice(0, 3); -} -``` - -> It might be confusing that a _union_ of types appears to have the _intersection_ of those types' properties. -> This is not an accident - the name _union_ comes from type theory. -> The _union_ `number | string` is composed by taking the union _of the values_ from each type. -> Notice that given two sets with corresponding facts about each set, only the _intersection_ of those facts applies to the _union_ of the sets themselves. -> For example, if we had a room of tall people wearing hats, and another room of Spanish speakers wearing hats, after combining those rooms, the only thing we know about _every_ person is that they must be wearing a hat. - -## Type Aliases - -We've been using object types and union types by writing them directly in type annotations. -This is convenient, but it's common to want to use the same type more than once and refer to it by a single name. - -A _type alias_ is exactly that - a _name_ for any _type_. -The syntax for a type alias is: - -```ts twoslash -type Point = { - x: number; - y: number; -}; - -// Exactly the same as the earlier example -function printCoord(pt: Point) { - console.log("The coordinate's x value is " + pt.x); - console.log("The coordinate's y value is " + pt.y); -} - -printCoord({ x: 100, y: 100 }); -``` - -You can actually use a type alias to give a name to any type at all, not just an object type. -For example, a type alias can name a union type: - -```ts twoslash -type ID = number | string; -``` - -Note that aliases are _only_ aliases - you cannot use type aliases to create different/distinct "versions" of the same type. -When you use the alias, it's exactly as if you had written the aliased type. -In other words, this code might _look_ illegal, but is OK according to TypeScript because both types are aliases for the same type: - -```ts twoslash -declare function getInput(): string; -declare function sanitize(str: string): string; -// ---cut--- -type UserInputSanitizedString = string; - -function sanitizeInput(str: string): UserInputSanitizedString { - return sanitize(str); -} - -// Create a sanitized input -let userInput = sanitizeInput(getInput()); - -// Can still be re-assigned with a string though -userInput = "new input"; -``` - -## Interfaces - -An _interface declaration_ is another way to name an object type: - -```ts twoslash -interface Point { - x: number; - y: number; -} - -function printCoord(pt: Point) { - console.log("The coordinate's x value is " + pt.x); - console.log("The coordinate's y value is " + pt.y); -} - -printCoord({ x: 100, y: 100 }); -``` - -Just like when we used a type alias above, the example works just as if we had used an anonymous object type. -TypeScript is only concerned with the _structure_ of the value we passed to `printCoord` - it only cares that it has the expected properties. -Being concerned only with the structure and capabilities of types is why we call TypeScript a _structurally typed_ type system. - -### Differences Between Type Aliases and Interfaces - -Type aliases and interfaces are very similar, and in many cases you can choose between them freely. -Almost all features of an `interface` are available in `type`, the key distinction is that a type cannot be re-opened to add new properties vs an interface which is always extendable. - - - - - - - - - - - - - - - - -
InterfaceType
-

Extending an interface

-
-interface Animal {
-  name: string
-}
-interface Bear extends Animal { - honey: boolean -}
-const bear = getBear() -bear.name -bear.honey -
-
-

Extending a type via intersections

-
-type Animal = {
-  name: string
-}
-type Bear = Animal & { - honey: boolean -}
-const bear = getBear(); -bear.name; -bear.honey; -
-
-

Adding new fields to an existing interface

-
-interface Window {
-  title: string
-}
-interface Window { - ts: TypeScriptAPI -}
-const src = 'const a = "Hello World"'; -window.ts.transpileModule(src, {}); -
-
-

A type cannot be changed after being created

-
-type Window = {
-  title: string
-}
-type Window = { - ts: TypeScriptAPI -}
- // Error: Duplicate identifier 'Window'.
-
-
- -You'll learn more about these concepts in later chapters, so don't worry if you don't understand all of these right away. - -- Prior to TypeScript version 4.2, type alias names [_may_ appear in error messages](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWZWhfYAjABMAMwALA+gbsVjoADqgjKESytQPxCHghAByXigYgBfr8LAsYj8aQMUASbDQcRSExCeCwFiIQh+AKfAYyBiQFgOPyIaikSGLQo0Zj-aazaY+dSaXjLDgAGXgAC9CKhDqAALxJaw2Ib2RzOISuDycLw+ImBYKQflCkWRRD2LXCw6JCxS1JCdJZHJ5RAFIbFJU8ADKC3WzEcnVZaGYE1ABpFnFOmsFhsil2uoHuzwArO9SmAAEIsSFrZB-GgAjjA5gtVN8VCEc1o1C4Q4AGlR2AwO1EsBQoAAbvB-gJ4HhPgB5aDwem-Ph1TCV3AEEirTp4ELtRbTPD4vwKjOfAuioSQHuDXBcnmgACC+eCONFEs73YAPGGZVT5cRyyhiHh7AAON7lsG3vBggB8XGV3l8-nVISOgghxoLq9i7io-AHsayRWGaFrlFauq2rg9qaIGQHwCBqChtKdgRo8TxRjeyB3o+7xAA), sometimes in place of the equivalent anonymous type (which may or may not be desirable). Interfaces will always be named in error messages. -- Type aliases may not participate [in declaration merging, but interfaces can](/play?#code/PTAEEEDtQS0gXApgJwGYEMDGjSfdAIx2UQFoB7AB0UkQBMAoEUfO0Wgd1ADd0AbAK6IAzizp16ALgYM4SNFhwBZdAFtV-UAG8GoPaADmNAcMmhh8ZHAMMAvjLkoM2UCvWad+0ARL0A-GYWVpA29gyY5JAWLJAwGnxmbvGgALzauvpGkCZmAEQAjABMAMwALLkANBl6zABi6DB8okR4Jjg+iPSgABboovDk3jjo5pbW1d6+dGb5djLwAJ7UoABKiJTwjThpnpnGpqPBoTLMAJrkArj4kOTwYmycPOhW6AR8IrDQ8N04wmo4HHQCwYi2Waw2W1S6S8HX8gTGITsQA). -- Interfaces may only be used to [declare the shapes of objects, not rename primitives](/play?#code/PTAEAkFMCdIcgM6gC4HcD2pIA8CGBbABwBtIl0AzUAKBFAFcEBLAOwHMUBPQs0XFgCahWyGBVwBjMrTDJMAshOhMARpD4tQ6FQCtIE5DWoixk9QEEWAeV37kARlABvaqDegAbrmL1IALlAEZGV2agBfampkbgtrWwMAJlAAXmdXdy8ff0Dg1jZwyLoAVWZ2Lh5QVHUJflAlSFxROsY5fFAWAmk6CnRoLGwmILzQQmV8JmQmDzI-SOiKgGV+CaYAL0gBBdyy1KCQ-Pn1AFFplgA5enw1PtSWS+vCsAAVAAtB4QQWOEMKBuYVUiVCYvYQsUTQcRSBDGMGmKSgAAa-VEgiQe2GLgKQA). -- Interface names will [_always_ appear in their original form](/play?#code/PTAEGEHsFsAcEsA2BTATqNrLusgzngIYDm+oA7koqIYuYQJ56gCueyoAUCKAC4AWHAHaFcoSADMaQ0PCG80EwgGNkALk6c5C1EtWgAsqOi1QAb06groEbjWg8vVHOKcAvpokshy3vEgyyMr8kEbQJogAFND2YREAlOaW1soBeJAoAHSIkMTRmbbI8e6aPMiZxJmgACqCGKhY6ABGyDnkFFQ0dIzMbBwCwqIccabcYLyQoKjIEmh8kwN8DLAc5PzwwbLMyAAeK77IACYaQSEjUWY2Q-YAjABMAMwALA+gbsVjNXW8yxySoAADaAA0CCaZbPh1XYqXgOIY0ZgmcK0AA0nyaLFhhGY8F4AHJmEJILCWsgZId4NNfIgGFdcIcUTVfgBlZTOWC8T7kAJ42G4eT+GS42QyRaYbCgXAEEguTzeXyCjDBSAAQSE8Ai0Xsl0K9kcziExDeiQs1lAqSE6SyOTy0AKQ2KHk4p1V6s1OuuoHuzwArMagA) in error messages, but _only_ when they are used by name. - -For the most part, you can choose based on personal preference, and TypeScript will tell you if it needs something to be the other kind of declaration. If you would like a heuristic, use `interface` until you need to use features from `type`. - -## Type Assertions - -Sometimes you will have information about the type of a value that TypeScript can't know about. - -For example, if you're using `document.getElementById`, TypeScript only knows that this will return _some_ kind of `HTMLElement`, but you might know that your page will always have an `HTMLCanvasElement` with a given ID. - -In this situation, you can use a _type assertion_ to specify a more specific type: - -```ts twoslash -const myCanvas = document.getElementById("main_canvas") as HTMLCanvasElement; -``` - -Like a type annotation, type assertions are removed by the compiler and won't affect the runtime behavior of your code. - -You can also use the angle-bracket syntax (except if the code is in a `.tsx` file), which is equivalent: - -```ts twoslash -const myCanvas = document.getElementById("main_canvas"); -``` - -> Reminder: Because type assertions are removed at compile-time, there is no runtime checking associated with a type assertion. -> There won't be an exception or `null` generated if the type assertion is wrong. - -TypeScript only allows type assertions which convert to a _more specific_ or _less specific_ version of a type. -This rule prevents "impossible" coercions like: - -```ts twoslash -// @errors: 2352 -const x = "hello" as number; -``` - -Sometimes this rule can be too conservative and will disallow more complex coercions that might be valid. -If this happens, you can use two assertions, first to `any` (or `unknown`, which we'll introduce later), then to the desired type: - -```ts twoslash -declare const expr: any; -type T = { a: 1; b: 2; c: 3 }; -// ---cut--- -const a = (expr as any) as T; -``` - -## Literal Types - -In addition to the general types `string` and `number`, we can refer to _specific_ strings and numbers in type positions. - -One way to think about this is to consider how JavaScript comes with different ways to declare a variable. Both `var` and `let` allow for changing what is held inside the variable, and `const` does not. This is reflected in how TypeScript creates types for literals. - -```ts twoslash -let changingString = "Hello World"; -changingString = "Olá Mundo"; -// Because `changingString` can represent any possible string, that -// is how TypeScript describes it in the type system -changingString; -// ^? - -const constantString = "Hello World"; -// Because `constantString` can only represent 1 possible string, it -// has a literal type representation -constantString; -// ^? -``` - -By themselves, literal types aren't very valuable: - -```ts twoslash -// @errors: 2322 -let x: "hello" = "hello"; -// OK -x = "hello"; -// ... -x = "howdy"; -``` - -It's not much use to have a variable that can only have one value! - -But by _combining_ literals into unions, you can express a much more useful concept - for example, functions that only accept a certain set of known values: - -```ts twoslash -// @errors: 2345 -function printText(s: string, alignment: "left" | "right" | "center") { - // ... -} -printText("Hello, world", "left"); -printText("G'day, mate", "centre"); -``` - -Numeric literal types work the same way: - -```ts twoslash -function compare(a: string, b: string): -1 | 0 | 1 { - return a === b ? 0 : a > b ? 1 : -1; -} -``` - -Of course, you can combine these with non-literal types: - -```ts twoslash -// @errors: 2345 -interface Options { - width: number; -} -function configure(x: Options | "auto") { - // ... -} -configure({ width: 100 }); -configure("auto"); -configure("automatic"); -``` - -There's one more kind of literal type: boolean literals. -There are only two boolean literal types, and as you might guess, they are the types `true` and `false`. -The type `boolean` itself is actually just an alias for the union `true | false`. - -### Literal Inference - -When you initialize a variable with an object, TypeScript assumes that the properties of that object might change values later. -For example, if you wrote code like this: - -```ts twoslash -declare const someCondition: boolean; -// ---cut--- -const obj = { counter: 0 }; -if (someCondition) { - obj.counter = 1; -} -``` - -TypeScript doesn't assume the assignment of `1` to a field which previously had `0` is an error. -Another way of saying this is that `obj.counter` must have the type `number`, not `0`, because types are used to determine both _reading_ and _writing_ behavior. - -The same applies to strings: - -```ts twoslash -// @errors: 2345 -declare function handleRequest(url: string, method: "GET" | "POST"): void; -// ---cut--- -const req = { url: "https://example.com", method: "GET" }; -handleRequest(req.url, req.method); -``` - -In the above example `req.method` is inferred to be `string`, not `"GET"`. Because code can be evaluated between the creation of `req` and the call of `handleRequest` which could assign a new string like `"GUESS"` to `req.method`, TypeScript considers this code to have an error. - -There are two ways to work around this. - -1. You can change the inference by adding a type assertion in either location: - - ```ts twoslash - declare function handleRequest(url: string, method: "GET" | "POST"): void; - // ---cut--- - // Change 1: - const req = { url: "https://example.com", method: "GET" as "GET" }; - // Change 2 - handleRequest(req.url, req.method as "GET"); - ``` - - Change 1 means "I intend for `req.method` to always have the _literal type_ `"GET"`", preventing the possible assignment of `"GUESS"` to that field after. - Change 2 means "I know for other reasons that `req.method` has the value `"GET"`". - -2. You can use `as const` to convert the entire object to be type literals: - - ```ts twoslash - declare function handleRequest(url: string, method: "GET" | "POST"): void; - // ---cut--- - const req = { url: "https://example.com", method: "GET" } as const; - handleRequest(req.url, req.method); - ``` - -The `as const` suffix acts like `const` but for the type system, ensuring that all properties are assigned the literal type instead of a more general version like `string` or `number`. - -## `null` and `undefined` - -JavaScript has two primitive values used to signal absent or uninitialized value: `null` and `undefined`. - -TypeScript has two corresponding _types_ by the same names. How these types behave depends on whether you have the `strictNullChecks` option on. - -### `strictNullChecks` off - -With `strictNullChecks` _off_, values that might be `null` or `undefined` can still be accessed normally, and the values `null` and `undefined` can be assigned to a property of any type. -This is similar to how languages without null checks (e.g. C#, Java) behave. -The lack of checking for these values tends to be a major source of bugs; we always recommend people turn `strictNullChecks` on if it's practical to do so in their codebase. - -### `strictNullChecks` on - -With `strictNullChecks` _on_, when a value is `null` or `undefined`, you will need to test for those values before using methods or properties on that value. -Just like checking for `undefined` before using an optional property, we can use _narrowing_ to check for values that might be `null`: - -```ts twoslash -function doSomething(x: string | null) { - if (x === null) { - // do nothing - } else { - console.log("Hello, " + x.toUpperCase()); - } -} -``` - -### Non-null Assertion Operator (Postfix `!`) - -TypeScript also has a special syntax for removing `null` and `undefined` from a type without doing any explicit checking. -Writing `!` after any expression is effectively a type assertion that the value isn't `null` or `undefined`: - -```ts twoslash -function liveDangerously(x?: number | null) { - // No error - console.log(x!.toFixed()); -} -``` - -Just like other type assertions, this doesn't change the runtime behavior of your code, so it's important to only use `!` when you know that the value _can't_ be `null` or `undefined`. - -## Enums - -Enums are a feature added to JavaScript by TypeScript which allows for describing a value which could be one of a set of possible named constants. Unlike most TypeScript features, this is _not_ a type-level addition to JavaScript but something added to the language and runtime. Because of this, it's a feature which you should know exists, but maybe hold off on using unless you are sure. You can read more about enums in the [Enum reference page](/docs/handbook/enums.html). - -## Less Common Primitives - -It's worth mentioning the rest of the primitives in JavaScript which are represented in the type system. -Though we will not go into depth here. - -##### `bigint` - -From ES2020 onwards, there is a primitive in JavaScript used for very large integers, `BigInt`: - -```ts twoslash -// @target: es2020 - -// Creating a bigint via the BigInt function -const oneHundred: bigint = BigInt(100); - -// Creating a BigInt via the literal syntax -const anotherHundred: bigint = 100n; -``` - -You can learn more about BigInt in [the TypeScript 3.2 release notes](/docs/handbook/release-notes/typescript-3-2.html#bigint). - -##### `symbol` - -There is a primitive in JavaScript used to create a globally unique reference via the function `Symbol()`: - -```ts twoslash -// @errors: 2367 -const firstName = Symbol("name"); -const secondName = Symbol("name"); - -if (firstName === secondName) { - // Can't ever happen -} -``` - -You can learn more about them in [Symbols reference page](/docs/handbook/symbols.html). diff --git a/docs/documentation/zh/handbook-v2/Modules.md b/docs/documentation/zh/handbook-v2/Modules.md deleted file mode 100644 index 29fbc09a..00000000 --- a/docs/documentation/zh/handbook-v2/Modules.md +++ /dev/null @@ -1,385 +0,0 @@ ---- -title: Modules -layout: docs -permalink: /docs/handbook/2/modules.html -oneline: "How JavaScript handles communicating across file boundaries." ---- - -JavaScript has a long history of different ways to handle modularizing code. -TypeScript having been around since 2012, has implemented support for a lot of these formats, but over time the community and the JavaScript specification has converged on a format called ES Modules (or ES6 modules). You might know it as the `import`/`export` syntax. - -ES Modules was added to the JavaScript spec in 2015, and by 2020 had broad support in most web browsers and JavaScript runtimes. - -For focus, the handbook will cover both ES Modules and its popular pre-cursor CommonJS `module.exports =` syntax, and you can find information about the other module patterns in the reference section under [Modules](/docs/handbook/modules.html). - -## How JavaScript Modules are Defined - -In TypeScript, just as in ECMAScript 2015, any file containing a top-level `import` or `export` is considered a module. - -Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well). - -Modules are executed within their own scope, not in the global scope. -This means that variables, functions, classes, etc. declared in a module are not visible outside the module unless they are explicitly exported using one of the export forms. -Conversely, to consume a variable, function, class, interface, etc. exported from a different module, it has to be imported using one of the import forms. - -## Non-modules - -Before we start, it's important to understand what TypeScript considers a module. -The JavaScript specification declares that any JavaScript files without an `export` or top-level `await` should be considered a script and not a module. - -Inside a script file variables and types are declared to be in the shared global scope, and it's assumed that you'll either use the [`--outFile`](/tsconfig#outFile) compiler option to join multiple input files into one output file, or use multiple ` - - - -
-
- Compiler:
- Framework: -
- - -``` - -## Test - -1. Run the project -2. As you type on the boxes you should see the message appear/change! - -![A GIF of Edge showing the code you have just wrote](https://media.giphy.com/media/U3mTibRAx34DG3zhAN/giphy.gif) - -## Debug - -1. In Edge, press F12 and click the Debugger tab. -2. Look in the first localhost folder, then scripts/app.ts -3. Put a breakpoint on the line with return. -4. Type in the boxes and confirm that the breakpoint hits in TypeScript code and that inspection works correctly. - -![An image showing the debugger running the code you have just wrote](/images/tutorials/aspnet/debugger.png) - -Congrats you've built your own .NET Core project with a TypeScript frontend. diff --git a/docs/documentation/zh/tutorials/Babel with TypeScript.md b/docs/documentation/zh/tutorials/Babel with TypeScript.md deleted file mode 100644 index a898289a..00000000 --- a/docs/documentation/zh/tutorials/Babel with TypeScript.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Using Babel with TypeScript -layout: docs -permalink: /docs/handbook/babel-with-typescript.html -oneline: How to create a hybrid Babel + TypeScript project -translatable: true ---- - -## Babel vs `tsc` for TypeScript - -When making a modern JavaScript project, you might ask yourself what is the right way to convert files from TypeScript to JavaScript? - -A lot of the time the answer is _"it depends"_, or _"someone may have decided for you"_ depending on the project. If you are building your project with an existing framework like [tsdx](https://tsdx.io), [Angular](https://angular.io/), [NestJS](https://nestjs.com/) or any framework mentioned in the [Getting Started](/docs/home) then this decision is handled for you. - -However, a useful heuristic could be: - -- Is your build output mostly the same as your source input files? Use `tsc` -- Do you need a build pipeline with multiple potential outputs? Use `babel` for transpiling and `tsc` for type checking - -## Babel for transpiling, `tsc` for types - -This is a common pattern for projects with existing build infrastructure which may have been ported from a JavaScript codebase to TypeScript. - -This technique is a hybrid approach, using Babel's [preset-typescript](https://babeljs.io/docs/en/babel-preset-typescript) to generate your JS files, and then using TypeScript to do type checking and `.d.ts` file generation. - -By using babel's support for TypeScript, you get the ability to work with existing build pipelines and are more likely to have a faster JS emit time because Babel does not type check your code. - -#### Type Checking and d.ts file generation - -The downside to using babel is that you don't get type checking during the transition from TS to JS. This can mean that type errors which you miss in your editor could sneak through into production code. - -In addition to that, Babel cannot create `.d.ts` files for your TypeScript which can make it harder to work with your project if it is a library. - -To fix these issues, you would probably want to set up a command to type check your project using TSC. This likely means duplicating some of your babel config into a corresponding [`tsconfig.json`](/tsconfig) and ensuring these flags are enabled: - -```json tsconfig -"compilerOptions": { - // Ensure that .d.ts files are created by tsc, but not .js files - "declaration": true, - "emitDeclarationOnly": true, - // Ensure that Babel can safely transpile files in the TypeScript project - "isolatedModules": true -} -``` - -For more information on these flags: - -- [`isolatedModules`](/tsconfig#isolatedModules) -- [`declaration`](/tsconfig#declaration), [`emitDeclarationOnly`](/tsconfig#emitDeclarationOnly) diff --git a/docs/documentation/zh/tutorials/DOM Manipulation.md b/docs/documentation/zh/tutorials/DOM Manipulation.md deleted file mode 100755 index 3e887001..00000000 --- a/docs/documentation/zh/tutorials/DOM Manipulation.md +++ /dev/null @@ -1,201 +0,0 @@ ---- -title: DOM Manipulation -layout: docs -permalink: /docs/handbook/dom-manipulation.html -oneline: Using the DOM with TypeScript -translatable: true ---- - -## DOM Manipulation - -### _An exploration into the `HTMLElement` type_ - -In the 20+ years since its standardization, JavaScript has come a very long way. While in 2020, JavaScript can be used on servers, in data science, and even on IoT devices, it is important to remember its most popular use case: web browsers. - -Websites are made up of HTML and/or XML documents. These documents are static, they do not change. The *Document Object Model (DOM)* is a programming interface implemented by browsers in order to make static websites functional. The DOM API can be used to change the document structure, style, and content. The API is so powerful that countless frontend frameworks (jQuery, React, Angular, etc.) have been developed around it in order to make dynamic websites even easier to develop. - -TypeScript is a typed superset of JavaScript, and it ships type definitions for the DOM API. These definitions are readily available in any default TypeScript project. Of the 20,000+ lines of definitions in _lib.dom.d.ts_, one stands out among the rest: `HTMLElement` . This type is the backbone for DOM manipulation with TypeScript. - -> You can explore the source code for the [DOM type definitions](https://github.com/microsoft/TypeScript/blob/main/lib/lib.dom.d.ts) - -## Basic Example - -Given a simplified _index.html_ file: - - - - TypeScript Dom Manipulation - -
- - - - - -Lets explore a TypeScript script that adds a `

Hello, World!

` element to the `#app` element. - -```ts -// 1. Select the div element using the id property -const app = document.getElementById("app"); - -// 2. Create a new

element programmatically -const p = document.createElement("p"); - -// 3. Add the text content -p.textContent = "Hello, World!"; - -// 4. Append the p element to the div element -app?.appendChild(p); -``` - -After compiling and running the _index.html_ page, the resulting HTML will be: - -```html -
-

Hello, World!

-
-``` - -## The `Document` Interface - -The first line of the TypeScript code uses a global variable `document`. Inspecting the variable shows it is defined by the `Document` interface from the _lib.dom.d.ts_ file. The code snippet contains calls to two methods, `getElementById` and `createElement`. - -### `Document.getElementById` - -The definition for this method is as follows: - -```ts -getElementById(elementId: string): HTMLElement | null; -``` - -Pass it an element id string and it will return either `HTMLElement` or `null` . This method introduces one of the most important types, `HTMLElement`. It serves as the base interface for every other element interface. For example, the `p` variable in the code example is of type `HTMLParagraphElement`. Also take note that this method can return `null`. This is because the method can't be certain pre-runtime if it will be able to actually find the specified element or not. In the last line of the code snippet, the new _optional chaining_ operator is used in order to call `appendChild`. - -### `Document.createElement` - -The definition for this method is (I have omitted the _deprecated_ definition): - -```ts -createElement(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]; -createElement(tagName: string, options?: ElementCreationOptions): HTMLElement; -``` - -This is an overloaded function definition. The second overload is simplest and works a lot like the `getElementById` method does. Pass it any `string` and it will return a standard HTMLElement. This definition is what enables developers to create unique HTML element tags. - -For example `document.createElement('xyz')` returns a `` element, clearly not an element that is specified by the HTML specification. - -> For those interested, you can interact with custom tag elements using the `document.getElementsByTagName` - -For the first definition of `createElement`, it is using some advanced generic patterns. It is best understood broken down into chunks, starting with the generic expression: ``. This expression defines a generic parameter `K` that is _constrained_ to the keys of the interface `HTMLElementTagNameMap`. The map interface contains every specified HTML tag name and its corresponding type interface. For example here are the first 5 mapped values: - -```ts -interface HTMLElementTagNameMap { - "a": HTMLAnchorElement; - "abbr": HTMLElement; - "address": HTMLElement; - "applet": HTMLAppletElement; - "area": HTMLAreaElement; - ... -} -``` - -Some elements do not exhibit unique properties and so they just return `HTMLElement`, but other types do have unique properties and methods so they return their specific interface (which will extend from or implement `HTMLElement`). - -Now, for the remainder of the `createElement` definition: `(tagName: K, options?: ElementCreationOptions): HTMLElementTagNameMap[K]`. The first argument `tagName` is defined as the generic parameter `K` . The TypeScript interpreter is smart enough to _infer_ the generic parameter from this argument. This means that the developer does not actually have to specify the generic parameter when using the method; whatever value is passed to the `tagName` argument will be inferred as `K` and thus can be used throughout the remainder of the definition. Which is exactly what happens; the return value `HTMLElementTagNameMap[K]` takes the `tagName` argument and uses it to return the corresponding type. This definition is how the `p` variable from the code snippet gets a type of `HTMLParagraphElement`. And if the code was `document.createElement('a')`, then it would be an element of type `HTMLAnchorElement`. - -## The `Node` interface - -The `document.getElementById` function returns an `HTMLElement`. `HTMLElement` interface extends the `Element` interface which extends the `Node` interface. This prototypal extension allows for all `HTMLElements` to utilize a subset of standard methods. In the code snippet, we use a property defined on the `Node` interface to append the new `p` element to the website. - -### `Node.appendChild` - -The last line of the code snippet is `app?.appendChild(p)`. The previous, `document.getElementById` , section detailed that the _optional chaining_ operator is used here because `app` can potentially be null at runtime. The `appendChild` method is defined by: - -```ts -appendChild(newChild: T): T; -``` - -This method works similarly to the `createElement` method as the generic parameter `T` is inferred from the `newChild` argument. `T` is _constrained_ to another base interface `Node`. - -## Difference between `children` and `childNodes` - -Previously, this document details the `HTMLElement` interface extends from `Element` which extends from `Node`. In the DOM API there is a concept of _children_ elements. For example in the following HTML, the `p` tags are children of the `div` element - -```tsx -
-

Hello, World

-

TypeScript!

-
; - -const div = document.getElementsByTagName("div")[0]; - -div.children; -// HTMLCollection(2) [p, p] - -div.childNodes; -// NodeList(2) [p, p] -``` - -After capturing the `div` element, the `children` prop will return a `HTMLCollection` list containing the `HTMLParagraphElements`. The `childNodes` property will return a similar `NodeList` list of nodes. Each `p` tag will still be of type `HTMLParagraphElements`, but the `NodeList` can contain additional _HTML nodes_ that the `HTMLCollection` list cannot. - -Modify the html by removing one of the `p` tags, but keep the text. - -```tsx -
-

Hello, World

- TypeScript! -
; - -const div = document.getElementsByTagName("div")[0]; - -div.children; -// HTMLCollection(1) [p] - -div.childNodes; -// NodeList(2) [p, text] -``` - -See how both lists change. `children` now only contains the `

Hello, World

` element, and the `childNodes` contains a `text` node rather than two `p` nodes. The `text` part of the `NodeList` is the literal `Node` containing the text `TypeScript!`. The `children` list does not contain this `Node` because it is not considered an `HTMLElement`. - -## The `querySelector` and `querySelectorAll` methods - -Both of these methods are great tools for getting lists of dom elements that fit a more unique set of constraints. They are defined in _lib.dom.d.ts_ as: - -```ts -/** - * Returns the first element that is a descendant of node that matches selectors. - */ -querySelector(selectors: K): HTMLElementTagNameMap[K] | null; -querySelector(selectors: K): SVGElementTagNameMap[K] | null; -querySelector(selectors: string): E | null; - -/** - * Returns all element descendants of node that match selectors. - */ -querySelectorAll(selectors: K): NodeListOf; -querySelectorAll(selectors: K): NodeListOf; -querySelectorAll(selectors: string): NodeListOf; -``` - -The `querySelectorAll` definition is similar to `getElementsByTagName`, except it returns a new type: `NodeListOf`. This return type is essentially a custom implementation of the standard JavaScript list element. Arguably, replacing `NodeListOf` with `E[]` would result in a very similar user experience. `NodeListOf` only implements the following properties and methods: `length` , `item(index)`, `forEach((value, key, parent) => void)` , and numeric indexing. Additionally, this method returns a list of _elements_, not _nodes_, which is what `NodeList` was returning from the `.childNodes` method. While this may appear as a discrepancy, take note that interface `Element` extends from `Node`. - -To see these methods in action modify the existing code to: - -```tsx -
    -
  • First :)
  • -
  • Second!
  • -
  • Third times a charm.
  • -
; - -const first = document.querySelector("li"); // returns the first li element -const all = document.querySelectorAll("li"); // returns the list of all li elements -``` - -## Interested in learning more? - -The best part about the _lib.dom.d.ts_ type definitions is that they are reflective of the types annotated in the Mozilla Developer Network (MDN) documentation site. For example, the `HTMLElement` interface is documented by this [HTMLElement page](https://developer.mozilla.org/docs/Web/API/HTMLElement) on MDN. These pages list all available properties, methods, and sometimes even examples. Another great aspect of the pages is that they provide links to the corresponding standard documents. Here is the link to the [W3C Recommendation for HTMLElement](https://www.w3.org/TR/html52/dom.html#htmlelement). - -Sources: - -- [ECMA-262 Standard](http://www.ecma-international.org/ecma-262/10.0/index.html) -- [Introduction to the DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) diff --git a/docs/documentation/zh/tutorials/Gulp.md b/docs/documentation/zh/tutorials/Gulp.md deleted file mode 100644 index ae089c0b..00000000 --- a/docs/documentation/zh/tutorials/Gulp.md +++ /dev/null @@ -1,467 +0,0 @@ ---- -title: Gulp -layout: docs -permalink: /docs/handbook/gulp.html -oneline: Using TypeScript with Gulp -deprecated: true ---- - -This quick start guide will teach you how to build TypeScript with [gulp](http://gulpjs.com) and then add [Browserify](http://browserify.org), [uglify](http://lisperator.net/uglifyjs/), or [Watchify](https://github.com/substack/watchify) to the gulp pipeline. -This guide also shows how to add [Babel](https://babeljs.io/) functionality using [Babelify](https://github.com/babel/babelify). - -We assume that you're already using [Node.js](https://nodejs.org/) with [npm](https://www.npmjs.com/). - -## Minimal project - -Let's start out with a new directory. -We'll name it `proj` for now, but you can change it to whatever you want. - -```shell -mkdir proj -cd proj -``` - -To start, we're going to structure our project in the following way: - -``` -proj/ - ├─ src/ - └─ dist/ -``` - -TypeScript files will start out in your `src` folder, run through the TypeScript compiler and end up in `dist`. - -Let's scaffold this out: - -```shell -mkdir src -mkdir dist -``` - -## Initialize the project - -Now we'll turn this folder into an npm package. - -```shell -npm init -``` - -You'll be given a series of prompts. -You can use the defaults except for your entry point. -For your entry point, use `./dist/main.js`. -You can always go back and change these in the `package.json` file that's been generated for you. - -## Install our dependencies - -Now we can use `npm install` to install packages. -First install `gulp-cli` globally (if you use a Unix system, you may need to prefix the `npm install` commands in this guide with `sudo`). - -```shell -npm install -g gulp-cli -``` - -Then install `typescript`, `gulp` and `gulp-typescript` in your project's dev dependencies. -[Gulp-typescript](https://www.npmjs.com/package/gulp-typescript) is a gulp plugin for TypeScript. - -```shell -npm install --save-dev typescript gulp@4.0.0 gulp-typescript -``` - -## Write a simple example - -Let's write a Hello World program. -In `src`, create the file `main.ts`: - -```ts -function hello(compiler: string) { - console.log(`Hello from ${compiler}`); -} -hello("TypeScript"); -``` - -In the project root, `proj`, create the file `tsconfig.json`: - -```json tsconfig -{ - "files": ["src/main.ts"], - "compilerOptions": { - "noImplicitAny": true, - "target": "es5" - } -} -``` - -## Create a `gulpfile.js` - -In the project root, create the file `gulpfile.js`: - -```js -var gulp = require("gulp"); -var ts = require("gulp-typescript"); -var tsProject = ts.createProject("tsconfig.json"); - -gulp.task("default", function () { - return tsProject.src().pipe(tsProject()).js.pipe(gulp.dest("dist")); -}); -``` - -## Test the resulting app - -```shell -gulp -node dist/main.js -``` - -The program should print "Hello from TypeScript!". - -## Add modules to the code - -Before we get to Browserify, let's build our code out and add modules to the mix. -This is the structure you're more likely to use for a real app. - -Create a file called `src/greet.ts`: - -```ts -export function sayHello(name: string) { - return `Hello from ${name}`; -} -``` - -Now change the code in `src/main.ts` to import `sayHello` from `greet.ts`: - -```ts -import { sayHello } from "./greet"; - -console.log(sayHello("TypeScript")); -``` - -Finally, add `src/greet.ts` to `tsconfig.json`: - -```json tsconfig -{ - "files": ["src/main.ts", "src/greet.ts"], - "compilerOptions": { - "noImplicitAny": true, - "target": "es5" - } -} -``` - -Make sure that the modules work by running `gulp` and then testing in Node: - -```shell -gulp -node dist/main.js -``` - -Notice that even though we used ES2015 module syntax, TypeScript emitted CommonJS modules that Node uses. -We'll stick with CommonJS for this tutorial, but you could set `module` in the options object to change this. - -## Browserify - -Now let's move this project from Node to the browser. -To do this, we'd like to bundle all our modules into one JavaScript file. -Fortunately, that's exactly what Browserify does. -Even better, it lets us use the CommonJS module system used by Node, which is the default TypeScript emit. -That means our TypeScript and Node setup will transfer to the browser basically unchanged. - -First, install browserify, [tsify](https://www.npmjs.com/package/tsify), and vinyl-source-stream. -tsify is a Browserify plugin that, like gulp-typescript, gives access to the TypeScript compiler. -vinyl-source-stream lets us adapt the file output of Browserify back into a format that gulp understands called [vinyl](https://github.com/gulpjs/vinyl). - -```shell -npm install --save-dev browserify tsify vinyl-source-stream -``` - -## Create a page - -Create a file in `src` named `index.html`: - -```html - - - - - Hello World! - - -

Loading ...

- - - -``` - -Now change `main.ts` to update the page: - -```ts -import { sayHello } from "./greet"; - -function showHello(divName: string, name: string) { - const elt = document.getElementById(divName); - elt.innerText = sayHello(name); -} - -showHello("greeting", "TypeScript"); -``` - -Calling `showHello` calls `sayHello` to change the paragraph's text. -Now change your gulpfile to the following: - -```js -var gulp = require("gulp"); -var browserify = require("browserify"); -var source = require("vinyl-source-stream"); -var tsify = require("tsify"); -var paths = { - pages: ["src/*.html"], -}; - -gulp.task("copy-html", function () { - return gulp.src(paths.pages).pipe(gulp.dest("dist")); -}); - -gulp.task( - "default", - gulp.series(gulp.parallel("copy-html"), function () { - return browserify({ - basedir: ".", - debug: true, - entries: ["src/main.ts"], - cache: {}, - packageCache: {}, - }) - .plugin(tsify) - .bundle() - .pipe(source("bundle.js")) - .pipe(gulp.dest("dist")); - }) -); -``` - -This adds the `copy-html` task and adds it as a dependency of `default`. -That means any time `default` is run, `copy-html` has to run first. -We've also changed `default` to call Browserify with the tsify plugin instead of gulp-typescript. -Conveniently, they both allow us to pass the same options object to the TypeScript compiler. - -After calling `bundle` we use `source` (our alias for vinyl-source-stream) to name our output bundle `bundle.js`. - -Test the page by running gulp and then opening `dist/index.html` in a browser. -You should see "Hello from TypeScript" on the page. - -Notice that we specified `debug: true` to Browserify. -This causes tsify to emit source maps inside the bundled JavaScript file. -Source maps let you debug your original TypeScript code in the browser instead of the bundled JavaScript. -You can test that source maps are working by opening the debugger for your browser and putting a breakpoint inside `main.ts`. -When you refresh the page the breakpoint should pause the page and let you debug `greet.ts`. - -## Watchify, Babel, and Uglify - -Now that we are bundling our code with Browserify and tsify, we can add various features to our build with browserify plugins. - -- Watchify starts gulp and keeps it running, incrementally compiling whenever you save a file. - This lets you keep an edit-save-refresh cycle going in the browser. - -- Babel is a hugely flexible compiler that converts ES2015 and beyond into ES5 and ES3. - This lets you add extensive and customized transformations that TypeScript doesn't support. - -- Uglify compacts your code so that it takes less time to download. - -## Watchify - -We'll start with Watchify to provide background compilation: - -```shell -npm install --save-dev watchify fancy-log -``` - -Now change your gulpfile to the following: - -```js -var gulp = require("gulp"); -var browserify = require("browserify"); -var source = require("vinyl-source-stream"); -var watchify = require("watchify"); -var tsify = require("tsify"); -var fancy_log = require("fancy-log"); -var paths = { - pages: ["src/*.html"], -}; - -var watchedBrowserify = watchify( - browserify({ - basedir: ".", - debug: true, - entries: ["src/main.ts"], - cache: {}, - packageCache: {}, - }).plugin(tsify) -); - -gulp.task("copy-html", function () { - return gulp.src(paths.pages).pipe(gulp.dest("dist")); -}); - -function bundle() { - return watchedBrowserify - .bundle() - .on("error", fancy_log) - .pipe(source("bundle.js")) - .pipe(gulp.dest("dist")); -} - -gulp.task("default", gulp.series(gulp.parallel("copy-html"), bundle)); -watchedBrowserify.on("update", bundle); -watchedBrowserify.on("log", fancy_log); -``` - -There are basically three changes here, but they require you to refactor your code a bit. - -1. We wrapped our `browserify` instance in a call to `watchify`, and then held on to the result. -2. We called `watchedBrowserify.on('update', bundle);` so that Browserify will run the `bundle` function every time one of your TypeScript files changes. -3. We called `watchedBrowserify.on('log', fancy_log);` to log to the console. - -Together (1) and (2) mean that we have to move our call to `browserify` out of the `default` task. -And we have to give the function for `default` a name since both Watchify and Gulp need to call it. -Adding logging with (3) is optional but very useful for debugging your setup. - -Now when you run Gulp, it should start and stay running. -Try changing the code for `showHello` in `main.ts` and saving it. -You should see output that looks like this: - -```shell -proj$ gulp -[10:34:20] Using gulpfile ~/src/proj/gulpfile.js -[10:34:20] Starting 'copy-html'... -[10:34:20] Finished 'copy-html' after 26 ms -[10:34:20] Starting 'default'... -[10:34:21] 2824 bytes written (0.13 seconds) -[10:34:21] Finished 'default' after 1.36 s -[10:35:22] 2261 bytes written (0.02 seconds) -[10:35:24] 2808 bytes written (0.05 seconds) -``` - -## Uglify - -First install Uglify. -Since the point of Uglify is to mangle your code, we also need to install vinyl-buffer and gulp-sourcemaps to keep sourcemaps working. - -```shell -npm install --save-dev gulp-uglify vinyl-buffer gulp-sourcemaps -``` - -Now change your gulpfile to the following: - -```js -var gulp = require("gulp"); -var browserify = require("browserify"); -var source = require("vinyl-source-stream"); -var tsify = require("tsify"); -var uglify = require("gulp-uglify"); -var sourcemaps = require("gulp-sourcemaps"); -var buffer = require("vinyl-buffer"); -var paths = { - pages: ["src/*.html"], -}; - -gulp.task("copy-html", function () { - return gulp.src(paths.pages).pipe(gulp.dest("dist")); -}); - -gulp.task( - "default", - gulp.series(gulp.parallel("copy-html"), function () { - return browserify({ - basedir: ".", - debug: true, - entries: ["src/main.ts"], - cache: {}, - packageCache: {}, - }) - .plugin(tsify) - .bundle() - .pipe(source("bundle.js")) - .pipe(buffer()) - .pipe(sourcemaps.init({ loadMaps: true })) - .pipe(uglify()) - .pipe(sourcemaps.write("./")) - .pipe(gulp.dest("dist")); - }) -); -``` - -Notice that `uglify` itself has just one call — the calls to `buffer` and `sourcemaps` exist to make sure sourcemaps keep working. -These calls give us a separate sourcemap file instead of using inline sourcemaps like before. -Now you can run Gulp and check that `bundle.js` does get minified into an unreadable mess: - -```shell -gulp -cat dist/bundle.js -``` - -## Babel - -First install Babelify and the Babel preset for ES2015. -Like Uglify, Babelify mangles code, so we'll need vinyl-buffer and gulp-sourcemaps. -By default Babelify will only process files with extensions of `.js`, `.es`, `.es6` and `.jsx` so we need to add the `.ts` extension as an option to Babelify. - -```shell -npm install --save-dev babelify@8 babel-core babel-preset-es2015 vinyl-buffer gulp-sourcemaps -``` - -Now change your gulpfile to the following: - -```js -var gulp = require("gulp"); -var browserify = require("browserify"); -var source = require("vinyl-source-stream"); -var tsify = require("tsify"); -var sourcemaps = require("gulp-sourcemaps"); -var buffer = require("vinyl-buffer"); -var paths = { - pages: ["src/*.html"], -}; - -gulp.task("copy-html", function () { - return gulp.src(paths.pages).pipe(gulp.dest("dist")); -}); - -gulp.task( - "default", - gulp.series(gulp.parallel("copy-html"), function () { - return browserify({ - basedir: ".", - debug: true, - entries: ["src/main.ts"], - cache: {}, - packageCache: {}, - }) - .plugin(tsify) - .transform("babelify", { - presets: ["es2015"], - extensions: [".ts"], - }) - .bundle() - .pipe(source("bundle.js")) - .pipe(buffer()) - .pipe(sourcemaps.init({ loadMaps: true })) - .pipe(sourcemaps.write("./")) - .pipe(gulp.dest("dist")); - }) -); -``` - -We also need to have TypeScript target ES2015. -Babel will then produce ES5 from the ES2015 code that TypeScript emits. -Let's modify `tsconfig.json`: - -```json tsconfig -{ - "files": ["src/main.ts"], - "compilerOptions": { - "noImplicitAny": true, - "target": "es2015" - } -} -``` - -Babel's ES5 output should be very similar to TypeScript's output for such a simple script. diff --git a/docs/documentation/zh/tutorials/Migrating from JavaScript.md b/docs/documentation/zh/tutorials/Migrating from JavaScript.md deleted file mode 100644 index be31153a..00000000 --- a/docs/documentation/zh/tutorials/Migrating from JavaScript.md +++ /dev/null @@ -1,442 +0,0 @@ ---- -title: Migrating from JavaScript -layout: docs -permalink: /docs/handbook/migrating-from-javascript.html -oneline: How to migrate from JavaScript to TypeScript ---- - -TypeScript doesn't exist in a vacuum. -It was built with the JavaScript ecosystem in mind, and a lot of JavaScript exists today. -Converting a JavaScript codebase over to TypeScript is, while somewhat tedious, usually not challenging. -In this tutorial, we're going to look at how you might start out. -We assume you've read enough of the handbook to write new TypeScript code. - -If you're looking to convert a React project, we recommend looking at the [React Conversion Guide](https://github.com/Microsoft/TypeScript-React-Conversion-Guide#typescript-react-conversion-guide) first. - -## Setting up your Directories - -If you're writing in plain JavaScript, it's likely that you're running your JavaScript directly, -where your `.js` files are in a `src`, `lib`, or `dist` directory, and then ran as desired. - -If that's the case, the files that you've written are going to be used as inputs to TypeScript, and you'll run the outputs it produces. -During our JS to TS migration, we'll need to separate our input files to prevent TypeScript from overwriting them. -If your output files need to reside in a specific directory, then that will be your output directory. - -You might also be running some intermediate steps on your JavaScript, such as bundling or using another transpiler like Babel. -In this case, you might already have a folder structure like this set up. - -From this point on, we're going to assume that your directory is set up something like this: - -``` -projectRoot -├── src -│ ├── file1.js -│ └── file2.js -├── built -└── tsconfig.json -``` - -If you have a `tests` folder outside of your `src` directory, you might have one `tsconfig.json` in `src`, and one in `tests` as well. - -## Writing a Configuration File - -TypeScript uses a file called `tsconfig.json` for managing your project's options, such as which files you want to include, and what sorts of checking you want to perform. -Let's create a bare-bones one for our project: - -```json -{ - "compilerOptions": { - "outDir": "./built", - "allowJs": true, - "target": "es5" - }, - "include": ["./src/**/*"] -} -``` - -Here we're specifying a few things to TypeScript: - -1. Read in any files it understands in the `src` directory (with `include`). -2. Accept JavaScript files as inputs (with `allowJs`). -3. Emit all of the output files in `built` (with `outDir`). -4. Translate newer JavaScript constructs down to an older version like ECMAScript 5 (using `target`). - -At this point, if you try running `tsc` at the root of your project, you should see output files in the `built` directory. -The layout of files in `built` should look identical to the layout of `src`. -You should now have TypeScript working with your project. - -## Early Benefits - -Even at this point you can get some great benefits from TypeScript understanding your project. -If you open up an editor like [VS Code](https://code.visualstudio.com) or [Visual Studio](https://visualstudio.com), you'll see that you can often get some tooling support like completion. -You can also catch certain bugs with options like: - -- `noImplicitReturns` which prevents you from forgetting to return at the end of a function. -- `noFallthroughCasesInSwitch` which is helpful if you never want to forget a `break` statement between `case`s in a `switch` block. - -TypeScript will also warn about unreachable code and labels, which you can disable with `allowUnreachableCode` and `allowUnusedLabels` respectively. - -## Integrating with Build Tools - -You might have some more build steps in your pipeline. -Perhaps you concatenate something to each of your files. -Each build tool is different, but we'll do our best to cover the gist of things. - -## Gulp - -If you're using Gulp in some fashion, we have a tutorial on [using Gulp](/docs/handbook/gulp.html) with TypeScript, and integrating with common build tools like Browserify, Babelify, and Uglify. -You can read more there. - -## Webpack - -Webpack integration is pretty simple. -You can use `ts-loader`, a TypeScript loader, combined with `source-map-loader` for easier debugging. -Simply run - -```shell -npm install ts-loader source-map-loader -``` - -and merge in options from the following into your `webpack.config.js` file: - -```js -module.exports = { - entry: "./src/index.ts", - output: { - filename: "./dist/bundle.js", - }, - - // Enable sourcemaps for debugging webpack's output. - devtool: "source-map", - - resolve: { - // Add '.ts' and '.tsx' as resolvable extensions. - extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"], - }, - - module: { - rules: [ - // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'. - { test: /\.tsx?$/, loader: "ts-loader" }, - - // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. - { test: /\.js$/, loader: "source-map-loader" }, - ], - }, - - // Other options... -}; -``` - -It's important to note that ts-loader will need to run before any other loader that deals with `.js` files. - -The same goes for [awesome-typescript-loader](https://github.com/TypeStrong/ts-loader), another TypeScript loader for Webpack. -You can read more about the differences between the two [here](https://github.com/s-panferov/awesome-typescript-loader#differences-between-ts-loader). - -You can see an example of using Webpack in our [tutorial on React and Webpack](/docs/handbook/react-&-webpack.html). - -## Moving to TypeScript Files - -At this point, you're probably ready to start using TypeScript files. -The first step is to rename one of your `.js` files to `.ts`. -If your file uses JSX, you'll need to rename it to `.tsx`. - -Finished with that step? -Great! -You've successfully migrated a file from JavaScript to TypeScript! - -Of course, that might not feel right. -If you open that file in an editor with TypeScript support (or if you run `tsc --pretty`), you might see red squiggles on certain lines. -You should think of these the same way you'd think of red squiggles in an editor like Microsoft Word. -TypeScript will still translate your code, just like Word will still let you print your documents. - -If that sounds too lax for you, you can tighten that behavior up. -If, for instance, you _don't_ want TypeScript to compile to JavaScript in the face of errors, you can use the `noEmitOnError` option. -In that sense, TypeScript has a dial on its strictness, and you can turn that knob up as high as you want. - -If you plan on using the stricter settings that are available, it's best to turn them on now (see [Getting Stricter Checks](#getting-stricter-checks) below). -For instance, if you never want TypeScript to silently infer `any` for a type without you explicitly saying so, you can use `noImplicitAny` before you start modifying your files. -While it might feel somewhat overwhelming, the long-term gains become apparent much more quickly. - -## Weeding out Errors - -Like we mentioned, it's not unexpected to get error messages after conversion. -The important thing is to actually go one by one through these and decide how to deal with the errors. -Often these will be legitimate bugs, but sometimes you'll have to explain what you're trying to do a little better to TypeScript. - -### Importing from Modules - -You might start out getting a bunch of errors like `Cannot find name 'require'.`, and `Cannot find name 'define'.`. -In these cases, it's likely that you're using modules. -While you can just convince TypeScript that these exist by writing out - -```ts -// For Node/CommonJS -declare function require(path: string): any; -``` - -or - -```ts -// For RequireJS/AMD -declare function define(...args: any[]): any; -``` - -it's better to get rid of those calls and use TypeScript syntax for imports. - -First, you'll need to enable some module system by setting TypeScript's `module` flag. -Valid options are `commonjs`, `amd`, `system`, and `umd`. - -If you had the following Node/CommonJS code: - -```js -var foo = require("foo"); - -foo.doStuff(); -``` - -or the following RequireJS/AMD code: - -```js -define(["foo"], function (foo) { - foo.doStuff(); -}); -``` - -then you would write the following TypeScript code: - -```ts -import foo = require("foo"); - -foo.doStuff(); -``` - -### Getting Declaration Files - -If you started converting over to TypeScript imports, you'll probably run into errors like `Cannot find module 'foo'.`. -The issue here is that you likely don't have _declaration files_ to describe your library. -Luckily this is pretty easy. -If TypeScript complains about a package like `lodash`, you can just write - -```shell -npm install -S @types/lodash -``` - -If you're using a module option other than `commonjs`, you'll need to set your `moduleResolution` option to `node`. - -After that, you'll be able to import lodash with no issues, and get accurate completions. - -### Exporting from Modules - -Typically, exporting from a module involves adding properties to a value like `exports` or `module.exports`. -TypeScript allows you to use top-level export statements. -For instance, if you exported a function like so: - -```js -module.exports.feedPets = function (pets) { - // ... -}; -``` - -you could write that out as the following: - -```ts -export function feedPets(pets) { - // ... -} -``` - -Sometimes you'll entirely overwrite the exports object. -This is a common pattern people use to make their modules immediately callable like in this snippet: - -```js -var express = require("express"); -var app = express(); -``` - -You might have previously written that like so: - -```js -function foo() { - // ... -} -module.exports = foo; -``` - -In TypeScript, you can model this with the `export =` construct. - -```ts -function foo() { - // ... -} -export = foo; -``` - -### Too many/too few arguments - -You'll sometimes find yourself calling a function with too many/few arguments. -Typically, this is a bug, but in some cases, you might have declared a function that uses the `arguments` object instead of writing out any parameters: - -```js -function myCoolFunction() { - if (arguments.length == 2 && !Array.isArray(arguments[1])) { - var f = arguments[0]; - var arr = arguments[1]; - // ... - } - // ... -} - -myCoolFunction( - function (x) { - console.log(x); - }, - [1, 2, 3, 4] -); -myCoolFunction( - function (x) { - console.log(x); - }, - 1, - 2, - 3, - 4 -); -``` - -In this case, we need to use TypeScript to tell any of our callers about the ways `myCoolFunction` can be called using function overloads. - -```ts -function myCoolFunction(f: (x: number) => void, nums: number[]): void; -function myCoolFunction(f: (x: number) => void, ...nums: number[]): void; -function myCoolFunction() { - if (arguments.length == 2 && !Array.isArray(arguments[1])) { - var f = arguments[0]; - var arr = arguments[1]; - // ... - } - // ... -} -``` - -We added two overload signatures to `myCoolFunction`. -The first checks states that `myCoolFunction` takes a function (which takes a `number`), and then a list of `number`s. -The second one says that it will take a function as well, and then uses a rest parameter (`...nums`) to state that any number of arguments after that need to be `number`s. - -### Sequentially Added Properties - -Some people find it more aesthetically pleasing to create an object and add properties immediately after like so: - -```js -var options = {}; -options.color = "red"; -options.volume = 11; -``` - -TypeScript will say that you can't assign to `color` and `volume` because it first figured out the type of `options` as `{}` which doesn't have any properties. -If you instead moved the declarations into the object literal themselves, you'd get no errors: - -```ts -let options = { - color: "red", - volume: 11, -}; -``` - -You could also define the type of `options` and add a type assertion on the object literal. - -```ts -interface Options { - color: string; - volume: number; -} - -let options = {} as Options; -options.color = "red"; -options.volume = 11; -``` - -Alternatively, you can just say `options` has the type `any` which is the easiest thing to do, but which will benefit you the least. - -### `any`, `Object`, and `{}` - -You might be tempted to use `Object` or `{}` to say that a value can have any property on it because `Object` is, for most purposes, the most general type. -However **`any` is actually the type you want to use** in those situations, since it's the most _flexible_ type. - -For instance, if you have something that's typed as `Object` you won't be able to call methods like `toLowerCase()` on it. -Being more general usually means you can do less with a type, but `any` is special in that it is the most general type while still allowing you to do anything with it. -That means you can call it, construct it, access properties on it, etc. -Keep in mind though, whenever you use `any`, you lose out on most of the error checking and editor support that TypeScript gives you. - -If a decision ever comes down to `Object` and `{}`, you should prefer `{}`. -While they are mostly the same, technically `{}` is a more general type than `Object` in certain esoteric cases. - -## Getting Stricter Checks - -TypeScript comes with certain checks to give you more safety and analysis of your program. -Once you've converted your codebase to TypeScript, you can start enabling these checks for greater safety. - -### No Implicit `any` - -There are certain cases where TypeScript can't figure out what certain types should be. -To be as lenient as possible, it will decide to use the type `any` in its place. -While this is great for migration, using `any` means that you're not getting any type safety, and you won't get the same tooling support you'd get elsewhere. -You can tell TypeScript to flag these locations down and give an error with the `noImplicitAny` option. - -### Strict `null` & `undefined` Checks - -By default, TypeScript assumes that `null` and `undefined` are in the domain of every type. -That means anything declared with the type `number` could be `null` or `undefined`. -Since `null` and `undefined` are such a frequent source of bugs in JavaScript and TypeScript, TypeScript has the `strictNullChecks` option to spare you the stress of worrying about these issues. - -When `strictNullChecks` is enabled, `null` and `undefined` get their own types called `null` and `undefined` respectively. -Whenever anything is _possibly_ `null`, you can use a union type with the original type. -So for instance, if something could be a `number` or `null`, you'd write the type out as `number | null`. - -If you ever have a value that TypeScript thinks is possibly `null`/`undefined`, but you know better, you can use the postfix `!` operator to tell it otherwise. - -```ts -declare var foo: string[] | null; - -foo.length; // error - 'foo' is possibly 'null' - -foo!.length; // okay - 'foo!' just has type 'string[]' -``` - -As a heads up, when using `strictNullChecks`, your dependencies may need to be updated to use `strictNullChecks` as well. - -### No Implicit `any` for `this` - -When you use the `this` keyword outside of classes, it has the type `any` by default. -For instance, imagine a `Point` class, and imagine a function that we wish to add as a method: - -```ts -class Point { - constructor(public x, public y) {} - getDistance(p: Point) { - let dx = p.x - this.x; - let dy = p.y - this.y; - return Math.sqrt(dx ** 2 + dy ** 2); - } -} -// ... - -// Reopen the interface. -interface Point { - distanceFromOrigin(): number; -} -Point.prototype.distanceFromOrigin = function () { - return this.getDistance({ x: 0, y: 0 }); -}; -``` - -This has the same problems we mentioned above - we could easily have misspelled `getDistance` and not gotten an error. -For this reason, TypeScript has the `noImplicitThis` option. -When that option is set, TypeScript will issue an error when `this` is used without an explicit (or inferred) type. -The fix is to use a `this`-parameter to give an explicit type in the interface or in the function itself: - -```ts -Point.prototype.distanceFromOrigin = function (this: Point) { - return this.getDistance({ x: 0, y: 0 }); -}; -``` diff --git a/docs/documentation/zh/tutorials/React.md b/docs/documentation/zh/tutorials/React.md deleted file mode 100644 index 773ea021..00000000 --- a/docs/documentation/zh/tutorials/React.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: React -layout: docs -permalink: /docs/handbook/react.html -oneline: Links to learn about TypeScript and React -translatable: true ---- - -TypeScript supports [JSX](/docs/handbook/jsx.html) and can correctly model the patterns used in React codebases like `useState`. - -### Getting Set Up With a React Project - -Today there are many frameworks which support TypeScript out of the box: - -- [Create React App](https://create-react-app.dev) - [TS docs](https://create-react-app.dev/docs/adding-typescript/) -- [Next.js](https://nextjs.org) - [TS docs](https://nextjs.org/learn/excel/typescript) -- [Gatsby](https://www.gatsbyjs.org) - [TS Docs](https://www.gatsbyjs.org/docs/typescript/) - -All of these are great starting points. We [use Gatsby](https://www.gatsbyjs.org/blog/2020-01-23-why-typescript-chose-gatsby/#reach-skip-nav) with TypeScript for [this website](https://github.com/microsoft/TypeScript-Website/), so that can also be a useful reference implementation. - -### Documentation - -Here are some of the best places to find up-to-date information on React and TypeScript: - -- [React TypeScript Cheatsheets](https://react-typescript-cheatsheet.netlify.app) -- [React & Redux in TypeScript](https://github.com/piotrwitek/react-redux-typescript-guide#react--redux-in-typescript---complete-guide) diff --git a/docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md b/docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md deleted file mode 100644 index b056c7f3..00000000 --- a/docs/documentation/zh/tutorials/TypeScript Tooling in 5 minutes.md +++ /dev/null @@ -1,187 +0,0 @@ ---- -title: TypeScript Tooling in 5 minutes -layout: docs -permalink: /docs/handbook/typescript-tooling-in-5-minutes.html -oneline: A tutorial to understand how to create a small website with TypeScript -translatable: true ---- - -Let's get started by building a simple web application with TypeScript. - -## Installing TypeScript - -There are two main ways to get the TypeScript available for your project: - -- Via npm (the Node.js package manager) -- By installing TypeScript's Visual Studio plugins - -Visual Studio 2017 and Visual Studio 2015 Update 3 include TypeScript by default. -If you didn't install TypeScript with Visual Studio, you can still [download it](/download). - -For npm users: - -```shell -> npm install -g typescript -``` - -## Building your first TypeScript file - -In your editor, type the following JavaScript code in `greeter.ts`: - -```ts twoslash -// @noImplicitAny: false -function greeter(person) { - return "Hello, " + person; -} - -let user = "Jane User"; - -document.body.textContent = greeter(user); -``` - -## Compiling your code - -We used a `.ts` extension, but this code is just JavaScript. -You could have copy/pasted this straight out of an existing JavaScript app. - -At the command line, run the TypeScript compiler: - -```shell -tsc greeter.ts -``` - -The result will be a file `greeter.js` which contains the same JavaScript that you fed in. -We're up and running using TypeScript in our JavaScript app! - -Now we can start taking advantage of some of the new tools TypeScript offers. -Add a `: string` type annotation to the 'person' function argument as shown here: - -```ts twoslash -function greeter(person: string) { - return "Hello, " + person; -} - -let user = "Jane User"; - -document.body.textContent = greeter(user); -``` - -## Type annotations - -Type annotations in TypeScript are lightweight ways to record the intended contract of the function or variable. -In this case, we intend the greeter function to be called with a single string parameter. -We can try changing the call greeter to pass an array instead: - -```ts twoslash -// @errors: 2345 -function greeter(person: string) { - return "Hello, " + person; -} - -let user = [0, 1, 2]; - -document.body.textContent = greeter(user); -``` - -Re-compiling, you'll now see an error: - -```shell -error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'. -``` - -Similarly, try removing all the arguments to the greeter call. -TypeScript will let you know that you have called this function with an unexpected number of parameters. -In both cases, TypeScript can offer static analysis based on both the structure of your code, and the type annotations you provide. - -Notice that although there were errors, the `greeter.js` file is still created. -You can use TypeScript even if there are errors in your code. But in this case, TypeScript is warning that your code will likely not run as expected. - -## Interfaces - -Let's develop our sample further. Here we use an interface that describes objects that have a firstName and lastName field. -In TypeScript, two types are compatible if their internal structure is compatible. -This allows us to implement an interface just by having the shape the interface requires, without an explicit `implements` clause. - -```ts twoslash -interface Person { - firstName: string; - lastName: string; -} - -function greeter(person: Person) { - return "Hello, " + person.firstName + " " + person.lastName; -} - -let user = { firstName: "Jane", lastName: "User" }; - -document.body.textContent = greeter(user); -``` - -## Classes - -Finally, let's extend the example one last time with classes. -TypeScript supports new features in JavaScript, like support for class-based object-oriented programming. - -Here we're going to create a `Student` class with a constructor and a few public fields. -Notice that classes and interfaces play well together, letting the programmer decide on the right level of abstraction. - -Also of note, the use of `public` on arguments to the constructor is a shorthand that allows us to automatically create properties with that name. - -```ts twoslash -class Student { - fullName: string; - constructor( - public firstName: string, - public middleInitial: string, - public lastName: string - ) { - this.fullName = firstName + " " + middleInitial + " " + lastName; - } -} - -interface Person { - firstName: string; - lastName: string; -} - -function greeter(person: Person) { - return "Hello, " + person.firstName + " " + person.lastName; -} - -let user = new Student("Jane", "M.", "User"); - -document.body.textContent = greeter(user); -``` - -Re-run `tsc greeter.ts` and you'll see the generated JavaScript is the same as the earlier code. -Classes in TypeScript are just a shorthand for the same prototype-based OO that is frequently used in JavaScript. - -## Running your TypeScript web app - -Now type the following in `greeter.html`: - -```html - - - - TypeScript Greeter - - - - - -``` - -Open `greeter.html` in the browser to run your first simple TypeScript web application! - -Optional: Open `greeter.ts` in Visual Studio, or copy the code into the TypeScript playground. -You can hover over identifiers to see their types. -Notice that in some cases these types are inferred automatically for you. -Re-type the last line, and see completion lists and parameter help based on the types of the DOM elements. -Put your cursor on the reference to the greeter function, and hit F12 to go to its definition. -Notice, too, that you can right-click on a symbol and use refactoring to rename it. - -The type information provided works together with the tools to work with JavaScript at application scale. -For more examples of what's possible in TypeScript, see the Samples section of the website. - -![Visual Studio picture](/images/docs/greet_person.png) From bb113beb47dc6bf59973f02c490126c96633a9d9 Mon Sep 17 00:00:00 2001 From: zhouLion Date: Sun, 12 Sep 2021 10:20:12 +0800 Subject: [PATCH 15/15] ZH translation: remove untranslated file --- .../zh/javascript/JSDoc Reference.md | 708 ------------------ 1 file changed, 708 deletions(-) delete mode 100644 docs/documentation/zh/javascript/JSDoc Reference.md diff --git a/docs/documentation/zh/javascript/JSDoc Reference.md b/docs/documentation/zh/javascript/JSDoc Reference.md deleted file mode 100644 index 842ed504..00000000 --- a/docs/documentation/zh/javascript/JSDoc Reference.md +++ /dev/null @@ -1,708 +0,0 @@ ---- -title: JSDoc Reference -layout: docs -permalink: /docs/handbook/jsdoc-supported-types.html -oneline: What JSDoc does TypeScript-powered JavaScript support? -translatable: true ---- - -The list below outlines which constructs are currently supported -when using JSDoc annotations to provide type information in JavaScript files. - -Note any tags which are not explicitly listed below (such as `@async`) are not yet supported. - -- [`@type`](#type) -- [`@param`](#param-and-returns) (or [`@arg`](#param-and-returns) or [`@argument`](#param-and-returns)) -- [`@returns`](#param-and-returns) (or [`@return`](#param-and-returns)) -- [`@typedef`](#typedef-callback-and-param) -- [`@callback`](#typedef-callback-and-param) -- [`@template`](#template) -- [`@class`](#constructor) (or [`@constructor`](#constructor)) -- [`@this`](#this) -- [`@extends`](#extends) (or [`@augments`](#extends)) -- [`@enum`](#enum) -- [`@deprecated`](#deprecated-comments) - -#### `class` extensions - -- [Property Modifiers](#jsdoc-property-modifiers) `@public`, `@private`, `@protected`, `@readonly` - -The meaning is usually the same, or a superset, of the meaning of the tag given at [jsdoc.app](https://jsdoc.app). -The code below describes the differences and gives some example usage of each tag. - -**Note:** You can use [the playground to explore JSDoc support](/play?useJavaScript=truee=4#example/jsdoc-support). - -## `@type` - -You can use the "@type" tag and reference a type name (either primitive, defined in a TypeScript declaration, or in a JSDoc "@typedef" tag). -You can use most JSDoc types and any TypeScript type, from [the most basic like `string`](/docs/handbook/basic-types.html) to [the most advanced, like conditional types](/docs/handbook/advanced-types.html). - -```js twoslash -/** - * @type {string} - */ -var s; - -/** @type {Window} */ -var win; - -/** @type {PromiseLike} */ -var promisedString; - -// You can specify an HTML Element with DOM properties -/** @type {HTMLElement} */ -var myElement = document.querySelector(selector); -element.dataset.myData = ""; -``` - -`@type` can specify a union type — for example, something can be either a string or a boolean. - -```js twoslash -/** - * @type {(string | boolean)} - */ -var sb; -``` - -Note that parentheses are optional for union types. - -```js twoslash -/** - * @type {string | boolean} - */ -var sb; -``` - -You can specify array types using a variety of syntaxes: - -```js twoslash -/** @type {number[]} */ -var ns; -/** @type {Array.} */ -var nds; -/** @type {Array} */ -var nas; -``` - -You can also specify object literal types. -For example, an object with properties 'a' (string) and 'b' (number) uses the following syntax: - -```js twoslash -/** @type {{ a: string, b: number }} */ -var var9; -``` - -You can specify map-like and array-like objects using string and number index signatures, using either standard JSDoc syntax or TypeScript syntax. - -```js twoslash -/** - * A map-like object that maps arbitrary `string` properties to `number`s. - * - * @type {Object.} - */ -var stringToNumber; - -/** @type {Object.} */ -var arrayLike; -``` - -The preceding two types are equivalent to the TypeScript types `{ [x: string]: number }` and `{ [x: number]: any }`. The compiler understands both syntaxes. - -You can specify function types using either TypeScript or Closure syntax: - -```js twoslash -/** @type {function(string, boolean): number} Closure syntax */ -var sbn; -/** @type {(s: string, b: boolean) => number} TypeScript syntax */ -var sbn2; -``` - -Or you can just use the unspecified `Function` type: - -```js twoslash -/** @type {Function} */ -var fn7; -/** @type {function} */ -var fn6; -``` - -Other types from Closure also work: - -```js twoslash -/** - * @type {*} - can be 'any' type - */ -var star; -/** - * @type {?} - unknown type (same as 'any') - */ -var question; -``` - -### Casts - -TypeScript borrows cast syntax from Closure. -This lets you cast types to other types by adding a `@type` tag before any parenthesized expression. - -```js twoslash -/** - * @type {number | string} - */ -var numberOrString = Math.random() < 0.5 ? "hello" : 100; -var typeAssertedNumber = /** @type {number} */ (numberOrString); -``` - -### Import types - -You can also import declarations from other files using import types. -This syntax is TypeScript-specific and differs from the JSDoc standard: - -```js twoslash -// @filename: types.d.ts -export type Pet = { - name: string, -}; - -// @filename: main.js -/** - * @param { import("./types").Pet } p - */ -function walk(p) { - console.log(`Walking ${p.name}...`); -} -``` - -import types can also be used in type alias declarations: - -```js twoslash -// @filename: types.d.ts -export type Pet = { - name: string, -}; -// @filename: main.js -// ---cut--- -/** - * @typedef { import("./types").Pet } Pet - */ - -/** - * @type {Pet} - */ -var myPet; -myPet.name; -``` - -import types can be used to get the type of a value from a module if you don't know the type, or if it has a large type that is annoying to type: - -```js twoslash -// @filename: accounts.d.ts -export const userAccount = { - name: "Name", - address: "An address", - postalCode: "", - country: "", - planet: "", - system: "", - galaxy: "", - universe: "", -}; -// @filename: main.js -// ---cut--- -/** - * @type {typeof import("./accounts").userAccount } - */ -var x = require("./accounts").userAccount; -``` - -## `@param` and `@returns` - -`@param` uses the same type syntax as `@type`, but adds a parameter name. -The parameter may also be declared optional by surrounding the name with square brackets: - -```js twoslash -// Parameters may be declared in a variety of syntactic forms -/** - * @param {string} p1 - A string param. - * @param {string=} p2 - An optional param (Closure syntax) - * @param {string} [p3] - Another optional param (JSDoc syntax). - * @param {string} [p4="test"] - An optional param with a default value - * @return {string} This is the result - */ -function stringsStringStrings(p1, p2, p3, p4) { - // TODO -} -``` - -Likewise, for the return type of a function: - -```js twoslash -/** - * @return {PromiseLike} - */ -function ps() {} - -/** - * @returns {{ a: string, b: number }} - May use '@returns' as well as '@return' - */ -function ab() {} -``` - -## `@typedef`, `@callback`, and `@param` - -`@typedef` may be used to define complex types. -Similar syntax works with `@param`. - -```js twoslash -/** - * @typedef {Object} SpecialType - creates a new type named 'SpecialType' - * @property {string} prop1 - a string property of SpecialType - * @property {number} prop2 - a number property of SpecialType - * @property {number=} prop3 - an optional number property of SpecialType - * @prop {number} [prop4] - an optional number property of SpecialType - * @prop {number} [prop5=42] - an optional number property of SpecialType with default - */ - -/** @type {SpecialType} */ -var specialTypeObject; -specialTypeObject.prop3; -``` - -You can use either `object` or `Object` on the first line. - -```js twoslash -/** - * @typedef {object} SpecialType1 - creates a new type named 'SpecialType' - * @property {string} prop1 - a string property of SpecialType - * @property {number} prop2 - a number property of SpecialType - * @property {number=} prop3 - an optional number property of SpecialType - */ - -/** @type {SpecialType1} */ -var specialTypeObject1; -``` - -`@param` allows a similar syntax for one-off type specifications. -Note that the nested property names must be prefixed with the name of the parameter: - -```js twoslash -/** - * @param {Object} options - The shape is the same as SpecialType above - * @param {string} options.prop1 - * @param {number} options.prop2 - * @param {number=} options.prop3 - * @param {number} [options.prop4] - * @param {number} [options.prop5=42] - */ -function special(options) { - return (options.prop4 || 1001) + options.prop5; -} -``` - -`@callback` is similar to `@typedef`, but it specifies a function type instead of an object type: - -```js twoslash -/** - * @callback Predicate - * @param {string} data - * @param {number} [index] - * @returns {boolean} - */ - -/** @type {Predicate} */ -const ok = (s) => !(s.length % 2); -``` - -Of course, any of these types can be declared using TypeScript syntax in a single-line `@typedef`: - -```js -/** @typedef {{ prop1: string, prop2: string, prop3?: number }} SpecialType */ -/** @typedef {(data: string, index?: number) => boolean} Predicate */ -``` - -## `@template` - -You can declare generic functions with the `@template` tag: - -```js twoslash -/** - * @template T - * @param {T} x - A generic parameter that flows through to the return type - * @return {T} - */ -function id(x) { - return x; -} - -const a = id("string"); -const b = id(123); -const c = id({}); -``` - -Use comma or multiple tags to declare multiple type parameters: - -```js -/** - * @template T,U,V - * @template W,X - */ -``` - -You can also specify a type constraint before the type parameter name. -Only the first type parameter in a list is constrained: - -```js twoslash -/** - * @template {string} K - K must be a string or string literal - * @template {{ serious(): string }} Seriousalizable - must have a serious method - * @param {K} key - * @param {Seriousalizable} object - */ -function seriousalize(key, object) { - // ???? -} -``` - -Declaring generic classes or types is unsupported. - -## Classes - -Classes can be declared as ES6 classes. - -```js twoslash -class C { - /** - * @param {number} data - */ - constructor(data) { - // property types can be inferred - this.name = "foo"; - - // or set explicitly - /** @type {string | null} */ - this.title = null; - - // or simply annotated, if they're set elsewhere - /** @type {number} */ - this.size; - - this.initialize(data); // Should error, initializer expects a string - } - /** - * @param {string} s - */ - initialize = function (s) { - this.size = s.length; - }; -} - -var c = new C(0); - -// C should only be called with new, but -// because it is JavaScript, this is allowed and -// considered an 'any'. -var result = C(1); -``` - -They can also be declared as constructor functions, as described in the next section: - -## `@constructor` - -The compiler infers constructor functions based on this-property assignments, but you can make checking stricter and suggestions better if you add a `@constructor` tag: - -```js twoslash -// @checkJs -// @errors: 2345 2348 -/** - * @constructor - * @param {number} data - */ -function C(data) { - // property types can be inferred - this.name = "foo"; - - // or set explicitly - /** @type {string | null} */ - this.title = null; - - // or simply annotated, if they're set elsewhere - /** @type {number} */ - this.size; - - this.initialize(data); -} -/** - * @param {string} s - */ -C.prototype.initialize = function (s) { - this.size = s.length; -}; - -var c = new C(0); -c.size; - -var result = C(1); -``` - -> Note: Error messages only show up in JS codebases with [a JSConfig](/docs/handbook/tsconfig-json.html) and [`checkJs`](/tsconfig#checkJs) enabled. - -With `@constructor`, `this` is checked inside the constructor function `C`, so you will get suggestions for the `initialize` method and an error if you pass it a number. Your editor may also show warnings if you call `C` instead of constructing it. - -Unfortunately, this means that constructor functions that are also callable cannot use `@constructor`. - -## `@this` - -The compiler can usually figure out the type of `this` when it has some context to work with. When it doesn't, you can explicitly specify the type of `this` with `@this`: - -```js twoslash -/** - * @this {HTMLElement} - * @param {*} e - */ -function callbackForLater(e) { - this.clientHeight = parseInt(e); // should be fine! -} -``` - -## `@extends` - -When Javascript classes extend a generic base class, there is nowhere to specify what the type parameter should be. The `@extends` tag provides a place for that type parameter: - -```js twoslash -/** - * @template T - * @extends {Set} - */ -class SortableSet extends Set { - // ... -} -``` - -Note that `@extends` only works with classes. Currently, there is no way for a constructor function extend a class. - -## `@enum` - -The `@enum` tag allows you to create an object literal whose members are all of a specified type. Unlike most object literals in Javascript, it does not allow other members. - -```js twoslash -/** @enum {number} */ -const JSDocState = { - BeginningOfLine: 0, - SawAsterisk: 1, - SavingComments: 2, -}; - -JSDocState.SawAsterisk; -``` - -Note that `@enum` is quite different from, and much simpler than, TypeScript's `enum`. However, unlike TypeScript's enums, `@enum` can have any type: - -```js twoslash -/** @enum {function(number): number} */ -const MathFuncs = { - add1: (n) => n + 1, - id: (n) => -n, - sub1: (n) => n - 1, -}; - -MathFuncs.add1; -``` - -## `@deprecated` Comments - -When a function, method, or property is deprecated you can let users know by marking it with a `/** @deprecated */` JSDoc comment. That information is surfaced in completion lists and as a suggestion diagnostic that editors can handle specially. In an editor like VS Code, deprecated values are typically displayed in a strike-through style ~~like this~~. - -```js -// @noErrors -/** @deprecated */ -const apiV1 = {}; -const apiV2 = {}; - -apiV; -// ^| -``` - -## More examples - -```js twoslash -class Foo {} -// ---cut--- -var someObj = { - /** - * @param {string} param1 - Docs on property assignments work - */ - x: function (param1) {}, -}; - -/** - * As do docs on variable assignments - * @return {Window} - */ -let someFunc = function () {}; - -/** - * And class methods - * @param {string} greeting The greeting to use - */ -Foo.prototype.sayHi = (greeting) => console.log("Hi!"); - -/** - * And arrow functions expressions - * @param {number} x - A multiplier - */ -let myArrow = (x) => x * x; - -/** - * Which means it works for stateless function components in JSX too - * @param {{a: string, b: number}} test - Some param - */ -var sfc = (test) =>
{test.a.charAt(0)}
; - -/** - * A parameter can be a class constructor, using Closure syntax. - * - * @param {{new(...args: any[]): object}} C - The class to register - */ -function registerClass(C) {} - -/** - * @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any') - */ -function fn10(p1) {} - -/** - * @param {...string} p1 - A 'rest' arg (array) of strings. (treated as 'any') - */ -function fn9(p1) { - return p1.join(); -} -``` - -## Patterns that are known NOT to be supported - -Referring to objects in the value space as types doesn't work unless the object also creates a type, like a constructor function. - -```js twoslash -function aNormalFunction() {} -/** - * @type {aNormalFunction} - */ -var wrong; -/** - * Use 'typeof' instead: - * @type {typeof aNormalFunction} - */ -var right; -``` - -Postfix equals on a property type in an object literal type doesn't specify an optional property: - -```js twoslash -/** - * @type {{ a: string, b: number= }} - */ -var wrong; -/** - * Use postfix question on the property name instead: - * @type {{ a: string, b?: number }} - */ -var right; -``` - -Nullable types only have meaning if `strictNullChecks` is on: - -```js twoslash -/** - * @type {?number} - * With strictNullChecks: true -- number | null - * With strictNullChecks: false -- number - */ -var nullable; -``` - -You can also use a union type: - -```js twoslash -/** - * @type {number | null} - * With strictNullChecks: true -- number | null - * With strictNullChecks: false -- number - */ -var unionNullable; -``` - -Non-nullable types have no meaning and are treated just as their original type: - -```js twoslash -/** - * @type {!number} - * Just has type number - */ -var normal; -``` - -Unlike JSDoc's type system, TypeScript only allows you to mark types as containing null or not. -There is no explicit non-nullability -- if strictNullChecks is on, then `number` is not nullable. -If it is off, then `number` is nullable. - -### Unsupported tags - -TypeScript ignores any unsupported JSDoc tags. - -The following tags have open issues to support them: - -- `@const` ([issue #19672](https://github.com/Microsoft/TypeScript/issues/19672)) -- `@inheritdoc` ([issue #23215](https://github.com/Microsoft/TypeScript/issues/23215)) -- `@memberof` ([issue #7237](https://github.com/Microsoft/TypeScript/issues/7237)) -- `@yields` ([issue #23857](https://github.com/Microsoft/TypeScript/issues/23857)) -- `{@link …}` ([issue #35524](https://github.com/Microsoft/TypeScript/issues/35524)) - -## JS Class extensions - -### JSDoc Property Modifiers - -From TypeScript 3.8 onwards, you can use JSDoc to modify the properties in a class. First are the accessibility modifiers: `@public`, `@private`, and `@protected`. -These tags work exactly like `public`, `private`, and `protected` respectively work in TypeScript. - -```js twoslash -// @errors: 2341 -// @ts-check - -class Car { - constructor() { - /** @private */ - this.identifier = 100; - } - - printIdentifier() { - console.log(this.identifier); - } -} - -const c = new Car(); -console.log(c.identifier); -``` - -- `@public` is always implied and can be left off, but means that a property can be reached from anywhere. -- `@private` means that a property can only be used within the containing class. -- `@protected` means that a property can only be used within the containing class, and all derived subclasses, but not on dissimilar instances of the containing class. - -Next, we've also added the `@readonly` modifier to ensure that a property is only ever written to during initialization. - -```js twoslash -// @errors: 2540 -// @ts-check - -class Car { - constructor() { - /** @readonly */ - this.identifier = 100; - } - - printIdentifier() { - console.log(this.identifier); - } -} - -const c = new Car(); -console.log(c.identifier); -```