kb.erickguedes.com
TypeScript: Tipagem e Produtividade

Funções e Classes

Aula 3 de 7

Arrow Functions Tipadas

// Sintaxe básica
const somar = (a: number, b: number): number => a + b;

// Inferência no retorno
const multiplicar = (a: number, b: number) => a * b;

// Void — função que não retorna valor
const log = (mensagem: string): void => {
  console.log(mensagem);
};

// Callback tipado
type Callback = (erro: Error | null, dados?: unknown) => void;

function buscarDados(url: string, cb: Callback) {
  // ...
}

Function Overloads

// Sobrecargas (declarações)
function processar(valor: string): string[];
function processar(valor: number): number[];
function processar(valor: boolean): boolean;

// Implementação (mais genérica)
function processar(valor: string | number | boolean): unknown {
  if (typeof valor === "string") return valor.split("");
  if (typeof valor === "number") return Array.from(String(valor), Number);
  return !valor;
}

// Uso
const arr = processar("abc");  // string[]
const nums = processar(123);   // number[]

this Parameter

type Contexto = { nome: string };

function saudacao(this: Contexto) {
  console.log(`Olá, ${this.nome}!`);
}

const ctx = { nome: "Alice" };
saudacao.call(ctx); // "Olá, Alice!"

// Erro: o this não tem o formato esperado
// saudacao.call({});

Classes

Modificadores de Acesso

class Animal {
  public nome: string;        // acesso público (padrão)
  protected idade: number;    // acesso na classe e subclasses
  private especie: string;    // acesso só na classe

  constructor(nome: string, idade: number, especie: string) {
    this.nome = nome;
    this.idade = idade;
    this.especie = especie;
  }

  public mover(): void {
    console.log(`${this.nome} está se movendo.`);
  }
}

class Cachorro extends Animal {
  constructor(nome: string, idade: number) {
    super(nome, idade, "Canino");
  }

  public latir(): void {
    console.log(`${this.nome} diz: Au au!`);
    // this.especie — Erro: private
  }
}

readonly e static

class Configuracao {
  static readonly VERSAO = "1.0.0";
  static instancia?: Configuracao;

  readonly id: string;
  private static contador = 0;

  constructor() {
    this.id = `cfg-${Configuracao.contador++}`;
  }

  static criar(): Configuracao {
    if (!this.instancia) {
      this.instancia = new Configuracao();
    }
    return this.instancia;
  }
}

console.log(Configuracao.VERSAO);
const cfg = Configuracao.criar();

Parameter Properties

Sintaxe concisa que declara e inicializa props no próprio construtor:

class Usuario {
  constructor(
    public readonly id: number,
    public nome: string,
    private email: string,
    protected role: string = "user",
  ) {}

  get contato(): string {
    return this.email;
  }

  set contato(valor: string) {
    if (!valor.includes("@")) throw new Error("Email inválido");
    this.email = valor;
  }
}

const user = new Usuario(1, "Alice", "[email protected]");
console.log(user.nome);
// user.id = 2; // Erro: readonly

Classes Abstratas

abstract class Forma {
  abstract calcularArea(): number;

  descrever(): string {
    return `Área: ${this.calcularArea()}`;
  }
}

class Circulo extends Forma {
  constructor(private raio: number) {
    super();
  }

  calcularArea(): number {
    return Math.PI * this.raio ** 2;
  }
}

// const forma = new Forma(); // Erro: não pode instanciar classe abstrata
const circulo = new Circulo(5);
console.log(circulo.descrever());

implements

interface Repositorio<T> {
  buscar(id: string): Promise<T | null>;
  salvar(item: T): Promise<void>;
  deletar(id: string): Promise<boolean>;
}

class RepositorioUsuario implements Repositorio<Usuario> {
  async buscar(id: string): Promise<Usuario | null> {
    // implementação
    return null;
  }

  async salvar(item: Usuario): Promise<void> {
    // implementação
  }

  async deletar(id: string): Promise<boolean> {
    return true;
  }
}

Method Override

class Base {
  protected dados: string[] = [];

  executar(): void {
    console.log("Base executando...");
  }
}

class Derivada extends Base {
  // Override: substitui método da classe pai
  executar(): void {
    console.log("Derivada executando antes...");
    super.executar(); // chama implementação da Base
    console.log("Derivada executando depois...");
  }
}

Lab: Sistema de Classes

abstract class Funcionario {
  constructor(
    public readonly id: number,
    public nome: string,
    protected salario: number,
  ) {}

  abstract calcularBonus(): number;

  aumentarSalario(percentual: number): void {
    this.salario += this.salario * (percentual / 100);
  }
}

class Desenvolvedor extends Funcionario {
  calcularBonus(): number {
    return this.salario * 0.1;
  }
}

class Gerente extends Funcionario {
  calcularBonus(): number {
    return this.salario * 0.2;
  }
}

const dev = new Desenvolvedor(1, "Alice", 8000);
const gerente = new Gerente(2, "Bob", 15000);

console.log(dev.calcularBonus());   // 800
console.log(gerente.calcularBonus()); // 3000
npx tsc --noEmit

Classes abstratas definem contratos com implementação parcial. implements força uma classe a seguir um contrato de interface. Parameter properties reduzem boilerplate no construtor.