programandoai

Parâmetros, retorno e valores opcionais

Uma função tipada é um contrato: promete que tipo de dado recebe e que tipo de dado devolve. Quebrar esse contrato vira diagnóstico na hora.

Estudar esta lição interativa →

Até agora você tipou variáveis. Mas o lugar onde a tipagem realmente compensa o esforço é nas funções, porque uma função é chamada de vários pontos diferentes do código, às vezes por outras pessoas do time, às vezes por você mesmo, meses depois, já tendo esquecido os detalhes. Anotar os parâmetros e o retorno transforma a assinatura da função num contrato explícito: promete o que ela espera receber, e promete o que ela devolve.

// Parâmetros e retorno tipados: a assinatura da função vira um contrato.
function calcularTotal(preco: number, quantidade: number): number {
  return preco * quantidade;
}

console.log(calcularTotal(19.9, 3));
// calcularTotal("19.9", 3); // erro: "19.9" não é number

Descomente a linha final (removendo os //) para ver o diagnóstico.

Repare que a anotação do retorno vem depois dos parênteses dos parâmetros: function calcularTotal(preco: number, quantidade: number): number. Se o corpo da função devolvesse, por engano, um texto em vez de um número (por exemplo, return "resultado: " + preco), o TypeScript acusaria isso também, mesmo sem nenhuma chamada errada em lugar nenhum: só de a implementação não bater com a promessa da assinatura, já é um diagnóstico.

Pense na assinatura de uma função como o cardápio de um restaurante: ele lista exatamente os ingredientes que um prato recebe e o que sai no final. Se a cozinha tentar entregar algo diferente do prometido no cardápio, alguém vai notar antes de o prato sair para a mesa. É exatamente esse tipo de checagem que a assinatura tipada garante para uma função.

Nem todo parâmetro é obrigatório. Duas formas cobrem a maioria dos casos, e vale saber diferenciar. Um parâmetro opcional, marcado com ? depois do nome, pode simplesmente não ser passado na chamada, e dentro da função ele vale undefined se ninguém o preencheu. Um parâmetro com valor padrão, escrito com = valor, também pode ser omitido, mas nesse caso ele já nasce preenchido com aquele valor combinado, sem passar por undefined. Compare os dois:

// Parâmetro opcional (?) e valor padrão: dois jeitos de tornar um
// argumento dispensável, cada um com uma diferença sutil.
function saudar(nome: string, saudacao?: string): string {
  return `${saudacao ?? "Olá"}, ${nome}!`;
}

function criarConta(nome: string, ativo: boolean = true): string {
  return `${nome} (${ativo ? "ativa" : "inativa"})`;
}

console.log(saudar("Ana"));
console.log(saudar("Bruno", "Bom dia"));
console.log(criarConta("Carla"));
FormaO que acontece se você não passar o argumento
saudacao?: stringO parâmetro vale undefined dentro da função
ativo: boolean = trueO parâmetro já chega preenchido com true

Os dois deixam o argumento dispensável na chamada, mas com comportamentos diferentes dentro da função.

Opcional precisa vir por último

Um parâmetro opcional (com ?) precisa vir depois dos parâmetros obrigatórios na lista. function f(a?: number, b: string) é um erro de tipo: o TypeScript não teria como saber, numa chamada com um único argumento, se ele é para a ou para b. Um parâmetro com valor padrão pode, tecnicamente, vir antes (quem chama passa undefined para usar o padrão), mas a convenção é colocá-lo também no fim.

// Sua vez! Complete a assinatura de "aplicarDesconto": preco é number,
// percentual é number opcional (usa 10 quando não vier) e a função
// devolve number.
function aplicarDesconto(preco: number, percentual?: number) {
  const p = percentual ?? 10;
  return preco - preco * (p / 100);
}

console.log(aplicarDesconto(100));
console.log(aplicarDesconto(100, 20));

Rode e confirme as duas chamadas.

← Voltar ao índice do curso