TypeScript: Dominando a Tipagem Estática

Aprenda TypeScript e torne seu código JavaScript mais seguro e robusto


TypeScript: Dominando a Tipagem Estática
1 Carregando...

TypeScript: Dominando a Tipagem Estática

TypeScript é um superset tipado de JavaScript que compila para JavaScript puro. Desenvolvido pela Microsoft e lançado em 2012, ele adiciona tipagem estática opcional e recursos avançados de orientação a objetos ao JavaScript, tornando o desenvolvimento de aplicações em larga escala mais seguro e produtivo.

Nota: TypeScript é construído sobre JavaScript. Se você precisa revisar os fundamentos, confira nosso Guia Completo de JavaScript antes de continuar.

Por que TypeScript?

TypeScript oferece benefícios significativos para equipes e projetos de qualquer tamanho:

  1. Detecção de Erros em Tempo de Compilação - Encontre bugs antes de executar o código
  2. IntelliSense Aprimorado - Autocompletar inteligente e documentação inline
  3. Refatoração Segura - Renomeie variáveis e funções com confiança
  4. Documentação Implícita - Tipos servem como documentação viva
  5. Escalabilidade - Mantenha projetos grandes organizados e seguros
  6. Adoção Gradual - Migre de JavaScript incrementalmente

Tipos Básicos

Tipos Primitivos

// Tipos simples
let nome: string = "Maria";
let idade: number = 25;
let ativo: boolean = true;
let nulo: null = null;
let indefinido: undefined = undefined;

// Arrays
let numeros: number[] = [1, 2, 3, 4, 5];
let nomes: Array<string> = ["Ana", "Pedro", "Carlos"];

// Tuplas
let coordenada: [number, number] = [10, 20];
let registro: [string, number, boolean] = ["Maria", 25, true];

// Enum
enum Status {
  Pendente = "PENDENTE",
  Aprovado = "APROVADO",
  Rejeitado = "REJEITADO"
}

let statusPedido: Status = Status.Pendente;

Tipos Avançados

// Union Types
type ID = string | number;
let userId: ID = "abc123";
userId = 42; // Também válido

// Intersection Types
type Pessoa = { nome: string };
type Funcionario = { cargo: string };
type FuncionarioPessoa = Pessoa & Funcionario;

// Literal Types
type Direcao = "norte" | "sul" | "leste" | "oeste";
let direcao: Direcao = "norte";

// Template Literal Types
type EventName = `on${Capitalize<string>}`;

// Nullable Types
let valorOpcional: string | null = null;
valorOpcional = "Valor definido";

Interfaces vs Types

// Interface - ideal para objetos e classes
interface Usuario {
  id: number;
  nome: string;
  email: string;
  readonly criadoEm: Date;
  endereco?: Endereco; // Propriedade opcional
}

interface Endereco {
  rua: string;
  cidade: string;
  pais: string;
}

// Extensão de interface
interface Admin extends Usuario {
  permissoes: string[];
  nivel: "junior" | "senior" | "master";
}

// Type alias - mais flexível
type Resultado<T> = 
  | { sucesso: true; dados: T }
  | { sucesso: false; erro: string };

type Callback<T> = (dados: T) => void;

Generics

// Função genérica
function primeiro<T>(array: T[]): T | undefined {
  return array[0];
}

const primeiroNumero = primeiro([1, 2, 3]); // number
const primeiraString = primeiro(["a", "b", "c"]); // string

// Classe genérica
class Pilha<T> {
  private items: T[] = [];

  push(item: T): void {
    this.items.push(item);
  }

  pop(): T | undefined {
    return this.items.pop();
  }

  peek(): T | undefined {
    return this.items[this.items.length - 1];
  }
}

// Constraints (restrições)
interface ComId {
  id: number;
}

function buscarPorId<T extends ComId>(items: T[], id: number): T | undefined {
  return items.find(item => item.id === id);
}

// Utility Types
type UsuarioSomenteLeitura = Readonly<Usuario>;
type UsuarioParcial = Partial<Usuario>;
type UsuarioSemEndereco = Omit<Usuario, "endereco">;
type SomenteNomeEmail = Pick<Usuario, "nome" | "email">;

Funções Tipadas

// Função com tipos explícitos
function calcularDesconto(
  preco: number,
  percentual: number
): number {
  return preco * (1 - percentual / 100);
}

// Arrow function tipada
const multiplicar = (a: number, b: number): number => a * b;

// Função com sobrecarga
function processar(valor: string): string;
function processar(valor: number): number;
function processar(valor: string | number): string | number {
  if (typeof valor === "string") {
    return valor.toUpperCase();
  }
  return valor * 2;
}

// Type guards
function isString(valor: unknown): valor is string {
  return typeof valor === "string";
}

function formatarValor(valor: unknown): string {
  if (isString(valor)) {
    return valor.trim();
  }
  return String(valor);
}

Classes com TypeScript

abstract class Entidade {
  constructor(
    public readonly id: string,
    public criadoEm: Date = new Date()
  ) {}

  abstract validar(): boolean;
}

class Produto extends Entidade {
  constructor(
    id: string,
    public nome: string,
    public preco: number,
    private _estoque: number = 0
  ) {
    super(id);
  }

  get estoque(): number {
    return this._estoque;
  }

  set estoque(valor: number) {
    if (valor < 0) {
      throw new Error("Estoque não pode ser negativo");
    }
    this._estoque = valor;
  }

  validar(): boolean {
    return this.nome.length > 0 && this.preco > 0;
  }

  aplicarDesconto(percentual: number): number {
    return this.preco * (1 - percentual / 100);
  }
}

// Implementando interfaces
interface Serializavel {
  toJSON(): string;
}

class Item implements Serializavel {
  constructor(public nome: string) {}

  toJSON(): string {
    return JSON.stringify({ nome: this.nome });
  }
}

Configuração do Projeto

tsconfig.json Recomendado

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "outDir": "./dist",
    "rootDir": "./src",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Checklist de Aprendizado

  • Dominar tipos primitivos e arrays
  • Entender interfaces e type aliases
  • Aprender generics e constraints
  • Estudar utility types (Partial, Readonly, Pick, Omit)
  • Praticar type guards e narrowing
  • Configurar projetos com tsconfig.json
  • Migrar um projeto JavaScript existente

Erros Comuns a Evitar

  • Usar any em todo lugar → Use unknown ou tipos específicos
  • Ignorar erros de compilação → Corrija todos os erros de tipo
  • Não usar strict mode → Sempre ative strict: true
  • Duplicar tipos → Use utility types para derivar tipos

Recursos Essenciais

Citação

“TypeScript é JavaScript que escala.” - Anders Hejlsberg, criador do TypeScript


TypeScript transforma a maneira como você escreve JavaScript. Invista tempo aprendendo seus recursos e sua produtividade aumentará significativamente!