|
| 1 | +--- |
| 2 | +title: Checando tipos de arquivos JavaScript |
| 3 | +layout: docs |
| 4 | +permalink: /pt/docs/handbook/type-checking-javascript-files.html |
| 5 | +oneline: Como adicionar checagem de tipos a arquivos JavaScript usando Typescript |
| 6 | +--- |
| 7 | + |
| 8 | +Aqui estão algumas diferenças notáveis em como a checagem de tipo funciona em arquivos `.js` comparados com arquivos `.ts`. |
| 9 | + |
| 10 | +## Propriedades são inferidas de atribuições no corpo das classes |
| 11 | + |
| 12 | +ES2015 não tem meios de declaração de propriedades em uma classe. Propriedades são atribuídas dinamicamente, assim como objetos literais. |
| 13 | + |
| 14 | +Em um arquivo `.js`, o compilador infere propriedades a partir da atribuição das mesmas dentro de um corpo de uma classe. |
| 15 | +O tipo de uma propriedade é o tipo dado no construtor, a não ser que não seja definido lá ou o tipo no construtor for undefined ou null. |
| 16 | +Neste caso, o tipo é uma união dos tipos de todos os valores que estão do lado direito dessas atribuições. |
| 17 | +Propriedades definidas no construtor são sempre assumidas existentes, enquanto as que foram definidas apenas em métodos, getters ou setters são consideradas opcionais. |
| 18 | + |
| 19 | +```js twoslash |
| 20 | +// @checkJs |
| 21 | +// @errors: 2322 |
| 22 | +class C { |
| 23 | + constructor() { |
| 24 | + this.constructorOnly = 0; |
| 25 | + this.constructorUnknown = undefined; |
| 26 | + } |
| 27 | + method() { |
| 28 | + this.constructorOnly = false; |
| 29 | + this.constructorUnknown = "plunkbat"; // ok, construtorUnknown é uma string | undefined |
| 30 | + this.methodOnly = "ok"; // ok, mas methodOnly também pode ser undefined |
| 31 | + } |
| 32 | + method2() { |
| 33 | + this.methodOnly = true; // também ok, methodOnly's type é string | boolean | undefined |
| 34 | + } |
| 35 | +} |
| 36 | +``` |
| 37 | + |
| 38 | +Se propriedades nunca forem declaradas no corpo da classe, elas são consideradas desconhecidas (com o tipo unknown). |
| 39 | +Se sua classe tem propriedades que são apenas lidas, adicione e então anote uma declaraçao no construtor com JSDoc para especificação de tipo. |
| 40 | +Você não precisa nem atribuir um valor a ela se for inicializada posteriormente. |
| 41 | + |
| 42 | +```js twoslash |
| 43 | +// @checkJs |
| 44 | +// @errors: 2322 |
| 45 | +class C { |
| 46 | + constructor() { |
| 47 | + /** @type {number | undefined} */ |
| 48 | + this.prop = undefined; |
| 49 | + /** @type {number | undefined} */ |
| 50 | + this.count; |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +let c = new C(); |
| 55 | +c.prop = 0; // OK |
| 56 | +c.count = "string"; |
| 57 | +``` |
| 58 | + |
| 59 | +## Funções construtoras são equivalentes a classes |
| 60 | + |
| 61 | +Antes do ES2015, Javascript usava funções construtoras ao invés de classes. |
| 62 | +O compilador suporta esse padrão e entende que funções construtoras são equivalentes a Classes do ES2015. |
| 63 | +As regras de inferência de propriedades funcionam exatamente da mesma forma. |
| 64 | + |
| 65 | +```js twoslash |
| 66 | +// @checkJs |
| 67 | +// @errors: 2683 2322 |
| 68 | +function C() { |
| 69 | + this.constructorOnly = 0; |
| 70 | + this.constructorUnknown = undefined; |
| 71 | +} |
| 72 | +C.prototype.method = function () { |
| 73 | + this.constructorOnly = false; |
| 74 | + this.constructorUnknown = "plunkbat"; // OK, o tipo é string | undefined |
| 75 | +}; |
| 76 | +``` |
| 77 | + |
| 78 | +## CommonJS modules são suportados |
| 79 | + |
| 80 | +Em um arquivo `.js`, TypeScript entende o formato de módulo CommonJS. |
| 81 | +Atribuiçoes a `exports` e `modules.exports` são reconhecidas como declarações de exportação. |
| 82 | +Similarmente, chamadas de função `require` são reconhecidas como importações de módulos. Por exemplo: |
| 83 | + |
| 84 | +```js |
| 85 | +// o mesmo que `import module "fs"` |
| 86 | +const fs = require("fs"); |
| 87 | + |
| 88 | +// o mesmo que `export funcion readFile` |
| 89 | +module.exports.readFile = function (f) { |
| 90 | + return fs.readFileSync(f); |
| 91 | +}; |
| 92 | +``` |
| 93 | + |
| 94 | +O suporte de módulo em Javascript é muito mais flexível sinteticamente que o suporte de módulo de TypeScript. |
| 95 | +Muitas das combinações de atribuições e declarações são suportadas. |
| 96 | + |
| 97 | +## Classes, funções, e object literals são namespaces |
| 98 | + |
| 99 | +Classes sao namespaces em arquivos `.js`. |
| 100 | +Isso pode ser usado para aninhar classes, por exemplo: |
| 101 | + |
| 102 | +```js twoslash |
| 103 | +class C {} |
| 104 | +C.D = class {}; |
| 105 | +``` |
| 106 | + |
| 107 | +E para código pre-ES2015, pode ser usado para simular métodos estáticos: |
| 108 | + |
| 109 | +```js twoslash |
| 110 | +function Outer() { |
| 111 | + this.y = 2; |
| 112 | +} |
| 113 | + |
| 114 | +Outer.Inner = function () { |
| 115 | + this.yy = 2; |
| 116 | +}; |
| 117 | + |
| 118 | +Outer.innter(); |
| 119 | +``` |
| 120 | + |
| 121 | +Também pode ser usado para criar namespaces simples: |
| 122 | + |
| 123 | +```js twoslash |
| 124 | +var ns = {}; |
| 125 | +ns.C = class {}; |
| 126 | +ns.func = function () {}; |
| 127 | + |
| 128 | +ns; |
| 129 | +``` |
| 130 | + |
| 131 | +Outras variantes são permitidas também: |
| 132 | + |
| 133 | +```js twoslash |
| 134 | +// IIFE |
| 135 | +var ns = (function (n) { |
| 136 | + return n || {}; |
| 137 | +})(); |
| 138 | +ns.CONST = 1; |
| 139 | + |
| 140 | +// defaulting to global |
| 141 | +var assign = |
| 142 | + assign || |
| 143 | + function () { |
| 144 | + // code goes here |
| 145 | + }; |
| 146 | +assign.extra = 1; |
| 147 | +``` |
| 148 | + |
| 149 | +## Objetos literais são abertos |
| 150 | + |
| 151 | +Em um arquivo `.ts`, um objeto literal que inicializa uma declaração de variável dá o seu tipo para a declaração. |
| 152 | +Nenhum membro novo que não foi especificado na declaração pode ser adicionado. |
| 153 | +Essas regras são relaxadas em um arquivo `.js`; objetos literais tem um tipo aberto (uma assinatura de índice) que permite adicionar e procurar propriedades que não foram adicionadas originalmente. |
| 154 | +Por exemplo: |
| 155 | + |
| 156 | +```js twoslash |
| 157 | +var obj = { a: 1 }; |
| 158 | +obj.b = 2; // Permitido |
| 159 | +``` |
| 160 | + |
| 161 | +Objetos literais se comportam como se tivessem uma assinatura de índice `[x:string]: any` que permite que sejam tratados como maps abertos ao invés de objetos fechados. |
| 162 | + |
| 163 | +Assim como outros comportamentos especiais do JS, esse comportamento pode ser mudado adicionando um tipo JSDoc para a variável. Por exemplo: |
| 164 | + |
| 165 | +```js twoslash |
| 166 | +// @checkJs |
| 167 | +// @errors: 2339 |
| 168 | +/** @type {{a: number}} */ |
| 169 | +var obj = { a: 1 }; |
| 170 | +obj.b = 2; |
| 171 | +``` |
| 172 | + |
| 173 | +## Inicializadores null, undefined e arrays vazios são do tipo any ou any[] |
| 174 | + |
| 175 | +Qualquer variável, parâmetro ou propriedade que é inicializado com null ou undefined terão tipo any, mesmo que a checagem estrita de null esteja habilitada. |
| 176 | +Qualquer variável, parâmetro ou propriedade que é inicializada com [] terá tipo any[], mesmo que a checagem estrita de null esteja habiltada. |
| 177 | +A única exceção é para propriedades que tem múltiplos inicializadores como descrito acima. |
| 178 | + |
| 179 | +```js twoslash |
| 180 | +function Foo(i = null) { |
| 181 | + if (!i) i = 1; |
| 182 | + var j = undefined; |
| 183 | + j = 2; |
| 184 | + this.l = []; |
| 185 | +} |
| 186 | + |
| 187 | +var foo = new Foo(); |
| 188 | +foo.l.push(foo.i); |
| 189 | +foo.l.push("end"); |
| 190 | +``` |
| 191 | + |
| 192 | +## Parâmetros de funções são opcionais por padrão |
| 193 | + |
| 194 | +Uma vez que não há uma forma de especificar opcionalidade em parâmetros de funções em Javascript pre-ES2015, todas os parâmetros de funções são considerados opcionais. |
| 195 | +Chamadas com menos argumentos que a quantidade declarada na função são permitidas. |
| 196 | + |
| 197 | +É importante notar que é um erro chamar funções com mais argumentos do que declarados. |
| 198 | + |
| 199 | +Por exemplo: |
| 200 | + |
| 201 | +```js twoslash |
| 202 | +// @checkJs |
| 203 | +// @strict: false |
| 204 | +// @errors: 7006 7006 2554 |
| 205 | +function bar(a, b) { |
| 206 | + console.log(a + " " + b); |
| 207 | +} |
| 208 | + |
| 209 | +bar(1); // OK, segundo argumento considerado opcional |
| 210 | +bar(1, 2); |
| 211 | +bar(1, 2, 3); // Erro, argumentos em excesso |
| 212 | +``` |
| 213 | + |
| 214 | +Funções anotadas com JSDoc são excluídas dessa regra. |
| 215 | +Use a sintaxe de parâmetro opcional JSDoc (`[` `]`) para expressar opcionalidade. e.g.: |
| 216 | + |
| 217 | +```js twoslash |
| 218 | +/** |
| 219 | + * @param {string} [somebody] - O nome de alguém. |
| 220 | + */ |
| 221 | +function sayHello(somebody) { |
| 222 | + if (!somebody) { |
| 223 | + somebody = "John Doe"; |
| 224 | + } |
| 225 | + console.log("Hello " + somebody); |
| 226 | +} |
| 227 | + |
| 228 | +sayHello(); |
| 229 | +``` |
| 230 | + |
| 231 | +## Declarações de parâmetros var-args são inferidos do uso de `arguments` |
| 232 | + |
| 233 | +Uma função que tem uma referência à referência `arguments` é considerada tendo parâmetros var-arg (i.e. `(...arg: any[]) => any`). Use a sintaxe de var-arg JSDoc para especificar o tipo destes argumentos. |
| 234 | + |
| 235 | +```js twoslash |
| 236 | +/** @param {...number} args */ |
| 237 | +function sum(/* numbers */) { |
| 238 | + var total = 0; |
| 239 | + for (var i = 0; i < arguments.length; i++) { |
| 240 | + total += arguments[i]; |
| 241 | + } |
| 242 | + return total; |
| 243 | +} |
| 244 | +``` |
| 245 | + |
| 246 | +## Tipos de parâmetros não especificados tem como padrão `any` |
| 247 | + |
| 248 | +Uma vez que não há sintaxe natual para especificar tipos de parâmetros genéricos em Javascript, um tipo de parâmetro não especificado tem como padrão `any`. |
| 249 | + |
| 250 | +### Em uma cláusula extends |
| 251 | + |
| 252 | +Por exemplo, `React.Component` é definido para ter dois parâmetros específicos, `Props` e `State`. |
| 253 | +Em um arquivo `.js`, não há forma legal de especificar esses parâmetros na cláusula extends. Por padrão o tipo dos argumentos será `any`: |
| 254 | + |
| 255 | +```js |
| 256 | +import { Component } from "react"; |
| 257 | + |
| 258 | +class MyComponent extends Component { |
| 259 | + render() { |
| 260 | + this.props.b; // Permitido, já que this.props tem o tipo any |
| 261 | + } |
| 262 | +} |
| 263 | +``` |
| 264 | + |
| 265 | +Use o JSDoc `@arguments` para especificar os tipos explicitamente. Por exemplo: |
| 266 | + |
| 267 | +```js |
| 268 | +import { Component } from "react"; |
| 269 | + |
| 270 | +/** |
| 271 | + * @augments {Component<{a: number}, State>} |
| 272 | + */ |
| 273 | +class MyComponent extends Component { |
| 274 | + render() { |
| 275 | + this.props.b; // Erro: b não existe em {a: number} |
| 276 | + } |
| 277 | +} |
| 278 | +``` |
| 279 | + |
| 280 | +### Em referências JSDoc |
| 281 | + |
| 282 | +Um tipo de argumento não especificado em JSDoc tem como padrão any |
| 283 | + |
| 284 | +```js twoslash |
| 285 | +/** @type{Array} */ |
| 286 | +var x = []; |
| 287 | + |
| 288 | +x.push(1); // OK |
| 289 | +x.push("string"); // OK, x é do tipo Array<any> |
| 290 | + |
| 291 | +/** @type{Array.<number>} */ |
| 292 | +var y = []; |
| 293 | + |
| 294 | +y.push(1); // OK |
| 295 | +y.push("string"); // Erro, string não é atribuível a number |
| 296 | +``` |
| 297 | + |
| 298 | +### Em chamadas de função |
| 299 | + |
| 300 | +Uma chamada para uma função genérica usa os argumentos para inferir o tipo dos parâmetros. As vezes este processo falha ao inferir qualquer tipo, principalmente por causa da falta de fontes de inferência; nesses casos, o tipo dos parâmetros será `any`. Por exemplo: |
| 301 | + |
| 302 | +```js |
| 303 | +var p = new Promise((resolve, reject) => { |
| 304 | + reject(); |
| 305 | +}); |
| 306 | + |
| 307 | +p; // Promise<any>; |
| 308 | +``` |
| 309 | + |
| 310 | +Para aprender todas as features disponíveis em JSDoc, veja [a referência](/docs/handbook/jsdoc-supported-types.html) |
0 commit comments