Skip to content

Commit 927b35d

Browse files
committed
Translate file Deep Dive
1 parent 095ec24 commit 927b35d

File tree

1 file changed

+232
-0
lines changed

1 file changed

+232
-0
lines changed
Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
---
2+
title: Análise profunda
3+
layout: docs
4+
permalink: /docs/handbook/declaration-files/deep-dive.html
5+
oneline: "Como arquivos d.ts funcionam, uma análise profunda"
6+
---
7+
8+
## Teoria do arquivo de declaração: Uma análise profunda
9+
10+
Estruturar módulos para obter a forma exata da API que você deseja pode ser complicado.
11+
Por exemplo, nós talvez queiramos um módulo que possa ser invocado com ou sem `new` para produzir diferentes tipos,
12+
que tenha uma variedade de tipos nomeados expostos em uma hierarquia,
13+
e que tenha algumas propriedades no objeto de módulo também.
14+
15+
Ao ler este guia, você terá as ferramentas para escrever arquivos de declaração complexos que expõem uma API amigável.
16+
Este guia se concentra em bibliotecas de módulo (ou UMD) pois as opções são mais variadas.
17+
18+
## Conceitos chaves
19+
20+
Você pode entender perfeitamente como criar qualquer forma de declaração
21+
ao compreender alguns conceitos chaves de como o TypeScript funciona.
22+
23+
### Tipos
24+
25+
Se você está lendo este guia, provavelmente já sabe de forma superficial o que é um tipo em TypeScript.
26+
Para ser mais explícito, no entanto, um _tipo_ é introduzido com:
27+
28+
- Uma declaração de alias de tipo (`type sn = number | string;`)
29+
- Uma declaração de interface (`interface I { x: number[]; }`)
30+
- Uma declaração de classe (`class C { }`)
31+
- Uma declaração de enum (`enum E { A, B, C }`)
32+
- Uma declaração `import` que se refere a um tipo
33+
34+
Cada uma dessas formas de declaração cria um novo nome de tipo.
35+
36+
### Valores
37+
38+
Assim como tipos, você provavelmente já entende o que um valor é.
39+
Valores são nomes em tempo de execução que podemos referenciar em expressões.
40+
Por exemplo `let x = 5;` cria um valor chamado `x`.
41+
42+
Novamente, sendo explícito, o itens seguintes criam valores:
43+
44+
- Declarações `let`, `const` e `var`
45+
- Uma declaração de `namespace` ou `module` que contém um valor
46+
- Uma declaração de `enum`
47+
- Uma declaração de `class`
48+
- Uma declaração `import` que se refere a um valor
49+
- Uma declaração de `function`
50+
51+
### Namespaces
52+
53+
Tipos podem existir em _namespaces_.
54+
Por exemplo, se temos a declaração `let x: A.B.C`,
55+
nós dizemos que o tipo `C` vem do namespace `A.B`.
56+
57+
Esta distinção é sutil e importante -- aqui, `A.B` não é necessariamente um tipo ou um valor.
58+
59+
## Combinações simples: Um nome, múltiplos significados
60+
61+
Dado um nome `A`, nós podemos encontrar até três significados para `A`: um tipo, um valor ou um namespace.
62+
Como o nome é interpretado depende do contexto em que ele é usado.
63+
Por exemplo, na declaração `let m: A.A = A;`,
64+
`A` é usado primeiro como um namespace, então como nome de tipo, e então como um valor.
65+
Esses significados podem acabar se referindo a declarações totalmente diferentes!
66+
67+
Isso pode parecer confuso, mas é muito conveniente contanto que nós não sobrecarreguemos excessivamente as coisas.
68+
Vejamos alguns aspectos úteis desta combinação de comportamento.
69+
70+
### Combinações integradas
71+
72+
Leitores atentos vão notar que, por exemplo, `class` apareceu em ambas as listas de _tipo_ e _valor_.
73+
A declaração `class C { }` cria duas coisas:
74+
um _tipo_ `C` que se refere à forma da instância da classe,
75+
e um _valor_ `C` que se refere à função construtora da classe.
76+
Declaração de enums se comportam de forma semelhante.
77+
78+
### Combinações de usuários
79+
80+
Digamos que escrevemos um arquivo de módulo `foo.d.ts`:
81+
82+
```ts
83+
export var SomeVar: { a: SomeType };
84+
export interface SomeType {
85+
count: number;
86+
}
87+
```
88+
89+
Em seguida, utilizarmos:
90+
91+
```ts
92+
import * as foo from "./foo";
93+
let x: foo.SomeType = foo.SomeVar.a;
94+
console.log(x.count);
95+
```
96+
97+
Isso funciona bem, mas podemos imaginar que `SomeType` e `SomeVar` são intimamente relacionados
98+
de forma que você gostaria que eles tivessem o mesmo nome.
99+
Nós podemos usar a combinação para apresentar esse dois objetos diferentes (o valor e o tipo) sob o mesmo nome `Bar`:
100+
101+
```ts
102+
export var Bar: { a: Bar };
103+
export interface Bar {
104+
count: number;
105+
}
106+
```
107+
108+
Isso apresenta uma oportunidade muito boa para desestruturação no código que o utiliza:
109+
110+
```ts
111+
import { Bar } from "./foo";
112+
let x: Bar = Bar.a;
113+
console.log(x.count);
114+
```
115+
116+
Novamente, nós usamos o `Bar` aqui como tipo e valor.
117+
Perceba que não precisamos declarar o valor `Bar` como sendo do tipo `Bar` -- eles são independentes.
118+
119+
## Combinações avançadas
120+
121+
Alguns tipos de declaração podem ser combinadas através de múltiplas declarações.
122+
Por exemplo, `class C { }` e `interface C { }` podem coexistir e ambas contribuem com propriedades para os tipos `C`.
123+
124+
Isso é permitido desde que não se crie um conflito.
125+
Uma regra geral é que os valores sempre entram em conflito com outro valores de mesmo nome a menos que sejam declaras como `namespace`s,
126+
tipos conflitarão se forem declarados com um alias de tipo (`type s = string`),
127+
e namespaces nunca entram em conflito.
128+
129+
Vamos ver como isso pode ser usado.
130+
131+
### Adicionar usando uma `interface`
132+
133+
Nós podemos adicionar membros adicionais à uma `interface` com outra declaração de `interface`:
134+
135+
```ts
136+
interface Foo {
137+
x: number;
138+
}
139+
// ... em outro local ...
140+
interface Foo {
141+
y: number;
142+
}
143+
let a: Foo = ...;
144+
console.log(a.x + a.y); // OK
145+
```
146+
147+
Isso também funciona com classes:
148+
149+
```ts
150+
class Foo {
151+
x: number;
152+
}
153+
// ... em outro local ...
154+
interface Foo {
155+
y: number;
156+
}
157+
let a: Foo = ...;
158+
console.log(a.x + a.y); // OK
159+
```
160+
161+
Perceba que não podemos adicionar ao alias de tipo (`type s = string;`) usando uma interface.
162+
163+
### Adicionar usando um `namespace`
164+
165+
Uma declaração de `namespace` pode ser usada adicionar novos tipos, valores, e namespaces de qualquer forma que não crie conflitos.
166+
167+
Por exemplo, podemos adicionar um membro estático a uma classe:
168+
169+
```ts
170+
class C {}
171+
// ... em outro local ...
172+
namespace C {
173+
export let x: number;
174+
}
175+
let y = C.x; // OK
176+
```
177+
178+
Perceba que neste exemplo, adicionamos um valor para o lado _estático_ de `C` (sua função construtora)
179+
Isto ocorre porque nós adicionamos um _valor_, e o contêiner para todos os valores é outro valor
180+
(tipos são contidos por namespaces), e namespaces são contidos por outros namespaces).
181+
182+
Nós também podemos adicionar um tipo com namespace a uma classe:
183+
184+
```ts
185+
class C {}
186+
// ... em outro local ...
187+
namespace C {
188+
export interface D {}
189+
}
190+
let y: C.D; // OK
191+
```
192+
193+
Neste exemplo, não havia um namespace `C` até nós escrevermos uma declaração de `namespace` para ele.
194+
O significado de `C` como um namespace não conflita com os significados de valor ou tipo de `C` criados pela classe.
195+
196+
Finalmente, podemos realizar diferentes mesclas usando declarações de `namespace`.
197+
Isto não é um exemplo particularmente realista, mas mostra vários tipos de comportamentos interessantes:
198+
199+
```ts
200+
namespace X {
201+
export interface Y {}
202+
export class Z {}
203+
}
204+
205+
// ... em outro local ...
206+
namespace X {
207+
export var Y: number;
208+
export namespace Z {
209+
export class C {}
210+
}
211+
}
212+
type X = string;
213+
```
214+
215+
Neste exemplo, o primeiro bloco cria os seguintes significados de nome:
216+
217+
- Um valor `X` (pois a declaração de `namespace` contém um valor, `Z`)
218+
- Um namespace `X` (pois a declaração de `namespace` contém um tipo, `Y`)
219+
- Um tipo `Y` no namespace `X`
220+
- Um tipo `Z` no namespace `X` (a forma da instância da classe)
221+
- Um valor `Z` que é uma propriedade do valor `X` (a função construtora da classe)
222+
223+
O segundo bloco cria os seguintes significados de nome:
224+
225+
- Um valor `Y` (do tipo `number`) que é uma propriedade do valor `X`
226+
- Um namespace `Z`
227+
- Um valor `Z` que é um propriedade do valor `X`
228+
- Um tipo `C` no namespace `X.Z`
229+
- Um valor `C` que é uma propriedade do valor `X.Z`
230+
- Um tipo `X`
231+
232+
<!-- TODO: Write more on that. -->

0 commit comments

Comments
 (0)