|
| 1 | +--- |
| 2 | +title: Análise profunda |
| 3 | +layout: docs |
| 4 | +permalink: /pt/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