Do's and Don'ts

Tipos Gerais

Number, String, Boolean, Symbol and Object

Nunca use os tipos Number, String, Boolean, Symbol, ou Object Esse tipos fazem referências a objetos não-primitivos que quase nunca são usados apropriadamente em códigos JavaScript.

ts
/* Errado */
function reverte(s: String): String;

Sempre use os tipos number, string, boolean, e symbol.

ts
/* OK */
function reverte(s: string): string;

Ao invés de Object, use o tipo não-primitivo object (adicionado em TypeScript 2.2).

Generics

Nunca tenha um tipo genérico que não use os tipos de seus parâmetros. Veja mais detalhes em TypeScript FAQ page.

any

Nunca use any como tipo a não ser que você esteja no processo de migração do projeto de JavaScript para Typescript. O compilador efetivamente trata any como “por favor desligue a verificação de tipo para essa coisa”. Isso é similar a botar um comentário @ts-ignore em volta de cada uso da variável. Isso pode ser muito útil quando você está migrando pela primeira vez um projeto JavaScript para TypeScript pois pode definir o tipo para coisas que você ainda não migrou como any, mas em um projeto TypeScript completo você estará desabilitando a verificação de tipos para qualquer parte do seu programa que o use.

Em casos onde você não sabe o tipo você quer aceitar, ou quando quer aceitar qualquer coisa pois irá passar adiante cegamente sem interagir, você pode usar unknown.

Tipos de Callback

Tipos de Retorno e Callbacks

Nunca use o tipo de retorno any para callbacks cujo o valor será ignorado:

ts
/* ERRADO */
function fn(x: () => any) {
x();
}

Sempre use o tipo de retorno void para callbacks cujo o valor será ignorado:

ts
/* OK */
function fn(x: () => void) {
x();
}

Por quê?: Usar void é mais seguro porque te previne de acidentalmente usar o valor de retorno de x de forma não verificada:

ts
function fn(x: () => void) {
var k = x(); // oops! deveria fazer outra coisa
k.facaAlgo(); // erro, mas ficaria OK se o tipo retorno tivesse sido 'any'
}

Parâmetros Opcionais em Callbacks

Nunca use parâmetros opcionais em callbacks a não ser que você realmente tenha essa intenção:

ts
/* ERRADO */
interface Buscador {
retornaObjeto(pronto: (data: any, tempoDecorrido?: number) => void): void;
}

Isso tem um significado muito especifico: o callback pronto pode ser invocado com 1 argumento ou pode ser invocado com 2 argumentos. O autor provavelmente teve a intenção de dizer que o callback talvez não se importe com o parâmetro tempoDecorrido, mas não tem necessidade de fazer o parâmetro opcional para atingir isso — sempre é valido prover um callback que aceita um numero menor de argumentos.

Sempre escreva parâmetros de callback como não-opcional:

ts
/* OK */
interface Buscador {
retornaObjeto(pronto: (data: any, tempoDecorrido: number) => void): void;
}

Sobrecargas e Callbacks

Nunca escreva sobrecargas separadas que diferem apenas na aridade do callback:

ts
/* ERRADO */
declare function antesDeTodos(acao: () => void, timeout?: number): void;
declare function antesDeTodos(
acao: (done: DoneFn) => void,
timeout?: number
): void;

Sempre escreva uma única sobrecarga usando a aridade maxima:

ts
/* OK */
declare function antesDeTodos(
acao: (done: DoneFn) => void,
timeout?: number
): void;

Por quê?: Sempre é válido para um callback desprezar um parâmetro, então não tem necessidade de encurtar a sobrecarga. Provendo um callback mais curto primeiro permite funções incorretamente tipadas serem passadas adiante porque possuem correspondência com a primeira sobrecarga.

Sobrecargas de Funções

Ordenação

Nunca ponha sobrecargas genérias antes das mais específicas:

ts
/* ERRADO */
declare function fn(x: any): any;
declare function fn(x: HTMLElement): number;
declare function fn(x: HTMLDivElement): string;
var meuElem: HTMLDivElement;
var x = fn(meuElem); // x: any, quê?

Sempre ordene sobrecargas pondo as assinaturas mais genéricas após as mais específicas:

ts
/* OK */
declare function fn(x: HTMLDivElement): string;
declare function fn(x: HTMLElement): number;
declare function fn(x: any): any;
var meuElem: HTMLDivElement;
var x = fn(meuElem); // x: string, :)

Por quê?: TypeScript escolhe a primeira sobrecarga com correspondência ao resolver chamadas as funções. Quando uma sobrecarga mais recente “é mais geral” do que uma mais antiga, a mais antiga é efetivamente omitida e não pode ser chamada.

Use Parâmetros Opcionais

Nunca escreva muitas sobrecargas que diferem apenas em nos parâmetros finais:

ts
/* ERRADO */
interface Exemplo {
diff(um: string): number;
diff(um: string, dois: string): number;
diff(um: string, dois: string, tres: boolean): number;
}

Sempre que possível use parâmetros opcionais:

ts
/* OK */
interface Exemplo {
diff(um: string, dois?: string, tres?: boolean): number;
}

Note que esse colapso deve ocorrer apenas quando todas as sobrecargas tiverem o mesmo tipo de retorno.

Por quê?: Isso é importante por dois motivos.

TypeScript resolve compatibilidade de assinaturas verificando se alguma assinatura do alvo pode ser chamada com os argumentos da fonte,e argumentos estranhos são permitidos. Esse código, por exemplo, expõe um bug apenas quando a assinatura é escrita corretamente usando parâmetros opcionais:

ts
function fn(x: (a: string, b: number, c: number) => void) {}
var x: Exemplo;
// Quando escrito com sobrecarga, OK -- usado a primeira sobrecarga
// Quando escrito com opcionais, devidamente um erro
fn(x.diff);

A segunda razão é quando um consumidor usa a funcionalidade “checagem estrita de nulos” do TypeScript. Porque parâmetros não especificados aparecem como undefined em javascript, geralmente é bom passar um undefined explícito para uma função com argumentos opcionais. Esse código, por exemplo, deveria ser OK sob nulos estritos:

ts
var x: Exemplo;
// Quando escrito com sobrecargas, um erro porque passa 'undefined' para 'string'
// Quando escrito com opcionais, devidamente OK
x.diff("algo", true ? undefined : "hora");

Use Tipos de União

Nunca escreva sobrecargas que diferem por tipo em apenas um argumento:

ts
/* ERRADO */
interface Momento {
utcOffset(): number;
utcOffset(b: number): Momento;
utcOffset(b: string): Momento;
}

Sempre que possível use tipos de união:

ts
/* OK */
interface Momento {
utcOffset(): number;
utcOffset(b: number | string): Momento;
}

Perceba que nós não fizemos b opcional aqui porque os tipos de retorno das assinaturas são diferentes. Por quê?: Isso é importante para pessoas que estão “passando adiante” um valor para sua função:

ts
function fn(x: string): void;
function fn(x: number): void;
function fn(x: number | string) {
// Quando escrito com sobrecargas separadas, indevidamente um erro
// Quando escrito com tipos de união,
// When written with union types, devidamente OK
return momento().utcOffset(x);
}

The TypeScript docs are an open source project. Help us improve these pages by sending a Pull Request

Contributors to this page:
MHMohamed Hegazy  (55)
  (6)
OTOrta Therox  (1)
VKVeniamin Krol  (1)
SSean  (1)
10+

Last updated: 20 de abr. de 2024