Skip to content

init translation of deep dive #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 26, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 71 additions & 103 deletions docs/documentation/zh/declaration-files/Deep Dive.md
Original file line number Diff line number Diff line change
@@ -1,83 +1,64 @@
---
title: Deep Dive
title: 深入探讨
layout: docs
permalink: /zh/docs/handbook/declaration-files/deep-dive.html
oneline: "How do d.ts files work, a deep dive"
oneline: "深入解析 d.ts 文件如何工作"
---

## 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.
构建模块以提供所需的精确 API 结构可能会相当复杂。例如,我们可能希望一个模块既可以在有 `new` 也可以在没有 `new` 的情况下被调用,以生成不同的类型,并且在层次结构中提供多种命名类型,同时还在模块对象上包含一些属性。

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.
通过阅读本指南,你将掌握编写复杂声明文件的技巧,从而提供友好的 API 接口。本指南专注于模块(或 UMD)库,因为它们更加灵活,选择更多。

## Key Concepts
## 关键概念

You can fully understand how to make any shape of declaration
by understanding some key concepts of how TypeScript works.
通过理解一些 TypeScript 的关键概念,你可以完全理解如何进行各种结构的声明。

### 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:
如果你在阅读本指南,你可能已经大致了解 TypeScript 中的类型。更明确地说,*类型(type)*是通过以下方式引入的:

- 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
- 类型别名声明(`type sn = number | string;`
- 接口声明(`interface I { x: number[]; }`
- 类声明(`class C { }`
- 枚举声明(`enum E { A, B, C }`
- 引用类型的 `import` 声明

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`.
和类型一样,你可能已经理解了值是什么。值是我们在表达式中可以引用的运行时名称。例如,`let x = 5;` 创建了一个名为 `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
- `let``const` `var` 声明
- 包含值的 `namespace` `module` 声明
- 枚举声明
- 类声明
- 引用值的 `import` 声明
- 函数声明

### 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.
类型可以存在于*命名空间*中。例如,如果我们声明 `let x: A.B.C`,我们会说类型 `C` 来自于 `A.B` 命名空间。

This distinction is subtle and important -- here, `A.B` is not necessarily a type or a value.
这种区别是微妙而重要的——在这里,`A.B` 不一定是一个类型或一个值。

## 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!
给定一个名称 `A`,我们可能会发现 `A` 有多达三种不同的含义:类型、值或命名空间。名称的解释取决于它所使用的上下文。例如,在声明 `let m: A.A = A;` 中,`A` 首先用作命名空间,然后用作类型名称,最后用作值。这些含义可能最终指向完全不同的声明!

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.
敏锐的读者会注意到,例如,`class` 在*类型*和*值*列表中都出现过。声明 `class C { }` 创建了两个东西:一个*类型* `C`,指的是类的实例结构,以及一个*值* `C`,指的是类的构造函数。枚举声明的行为类似。

### User Combinations
### 用户组合

Let's say we wrote a module file `foo.d.ts`:
假设我们写了一个模块文件 `foo.d.ts`

```ts
export var SomeVar: { a: SomeType };
@@ -86,17 +67,15 @@ export interface SomeType {
}
```

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`:
这样工作得很好,但我们可能想象 `SomeType` 和 `SomeVar` 非常密切相关,以至于希望它们有相同的名称。我们可以使用组合将这两个不同的对象(值和类型)以相同的名称 `Bar` 展现出来:

```ts
export var Bar: { a: Bar };
@@ -105,104 +84,95 @@ export interface Bar {
}
```

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.
同样,我们在这里将 `Bar` 用作了类型和值。请注意,我们不需要将 `Bar` 值声明为 `Bar` 类型——它们是独立的。

## 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.
某些类型的声明可以跨多个声明进行组合。例如,`class C { }` 和 `interface C { }` 可以共存,并且都可以向 `C` 类型贡献属性。

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.
只要不产生冲突,这样的组合是合法的。一般来说,值总是与同名的其他值冲突,除非它们被声明为 `namespace`;而类型如果用类型别名声明(`type s = string`)则会冲突,命名空间之间则永远不会冲突。

Let's see how this can be used.
让我们看看如何使用这一点。

### Adding using an `interface`
### 使用 `interface` 添加成员

We can add additional members to an `interface` with another `interface` declaration:
我们可以通过一个 `interface` 声明向另一个 `interface` 添加额外的成员:

```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.
请注意,我们不能使用接口向类型别名(`type s = string;`)添加成员。

### Adding using a `namespace`
### 使用 `namespace` 添加成员

A `namespace` declaration can be used to add new types, values, and namespaces in any way which does not create a conflict.
`namespace` 声明可以用来以不产生冲突的方式添加新的类型、值和命名空间。

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).
请注意,在这个例子中,我们向 `C` 的*静态*部分(其构造函数)添加了一个值。这是因为我们添加了一个*值*,而所有值的容器是另一个值(类型由命名空间包含,命名空间又由其他命名空间包含)。

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.
在这个例子中,在我们为 `C` 编写 `namespace` 声明之前,并没有命名空间 `C`。`C` 作为命名空间的含义与由类创建的值或类型 `C` 的含义不冲突。

Finally, we could perform many different merges using `namespace` declarations.
This isn't a particularly realistic example, but shows all sorts of interesting behavior:
最后,我们可以使用 `namespace` 声明进行多种不同的合并。虽然这不是一个特别现实的例子,但展示了各种有趣的行为:

```ts
namespace X {
export interface Y {}
export class Z {}
}

// ... elsewhere ...
// ... 在其他地方 ...
namespace X {
export var Y: number;
export namespace Z {
@@ -212,21 +182,19 @@ namespace X {
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)
- 一个值 `X`(因为 `namespace` 声明包含一个值 `Z`
- 一个命名空间 `X`(因为 `namespace` 声明包含一个类型 `Y`
- 一个在 `X` 命名空间中的类型 `Y`
- 一个在 `X` 命名空间中的类型 `Z`(类的实例结构)
- 一个作为 `X` 值属性的值 `Z`(类的构造函数)

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`

<!-- TODO: Write more on that. -->
- 一个值 `Y`(类型为 `number`),是 `X` 值的属性
- 一个命名空间 `Z`
- 一个作为 `X` 值属性的值 `Z`
- 一个在 `X.Z` 命名空间中的类型 `C`
- 一个作为 `X.Z` 值属性的值 `C`
- 一个类型 `X`