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 é numberDescomente 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"));| Forma | O que acontece se você não passar o argumento |
|---|---|
saudacao?: string | O parâmetro vale undefined dentro da função |
ativo: boolean = true | O parâmetro já chega preenchido com true |
Os dois deixam o argumento dispensável na chamada, mas com comportamentos diferentes dentro da função.
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.