Menu

Funções em TypeScript: tipos de parâmetro, retorno e void

Como tipar funções em TypeScript: anote cada parâmetro, anote ou deixe inferir o tipo de retorno, use void para funções que não retornam nada e tipe arrow functions, function expressions, funções async e o parâmetro this.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Uma função TypeScript é uma função JavaScript com tipos nos parâmetros e, opcionalmente, no valor de retorno. Cada parâmetro recebe uma anotação, o tipo de retorno vai depois da lista de parâmetros, e o compilador verifica cada chamada contra os dois.

As duas chamadas erradas são erros de compilação (TS2345 e TS2554). Os comentários // @ts-expect-error dizem ao compilador que um erro é esperado na linha seguinte, então o resto do arquivo continua rodando. Remova um deles e rode de novo para ver a mensagem real.

Tipos de parâmetro

Cada parâmetro é escrito name: Type. Com strict, que vem ligado por padrão no TypeScript 7, um parâmetro sem anotação e sem contexto para inferir é um erro: Parameter 'x' implicitly has an 'any' type. (TS7006). Então, na prática, todo parâmetro de uma função avulsa é anotado.

Qualquer tipo serve como tipo de parâmetro: primitivos, arrays, tipos de objeto, unions, outras funções.

O TypeScript também verifica o número de argumentos. Passar mais ou menos do que a função declara é um erro, diferente do JavaScript puro, que preenche os que faltam com undefined e ignora os extras. Para tornar um parâmetro opcional ou dar a ele um valor padrão, veja parâmetros opcionais.

Tipos de retorno: anotar ou inferir

O tipo de retorno vem depois do parêntese de fechamento: function f(): Type. Ele é opcional. Sem ele, o TypeScript infere o tipo a partir de cada return do corpo.

Uma anotação vale a pena quando a função é exportada, quando tem vários caminhos de retorno ou quando é recursiva. O erro então aparece dentro da função, no return errado, e não em quem chama. Um caso clássico é um ramo que esquece de retornar:

O compilador mostra index.ts(2,32): error TS2366: Function lacks ending return statement and return type does not include 'undefined'. Adicione um return "C"; no final e ele roda. Sem a anotação : string, a função compilaria com o tipo inferido "A" | "B" | undefined, e o problema passaria para quem usa o resultado.

void: funções que não retornam nada

Uma função que só faz algo (imprime no log, grava, altera dados) tem o tipo de retorno void. É o que o TypeScript infere quando não há return com valor, e você pode escrevê-lo explicitamente.

Estas regras sobre void surpreendem as pessoas:

SituaçãoPermitido?
function f(): void { return 42; }Não: Type 'number' is not assignable to type 'void'. (TS2322)
const f: () => void = () => 42;Sim: o valor é retornado, mas quem chama não pode depender dele
function f(): undefined {}Sim (TypeScript 5.1 e posteriores)
Usar o resultado de uma função void em um ifNão: An expression of type 'void' cannot be tested for truthiness. (TS1345)

A segunda linha é proposital. É por isso que arr.forEach(x => list.push(x)) compila, mesmo que push retorne um número. void em um tipo de função significa "seja o que for que isto retorne, ninguém lê". Para uma função que nunca retorna (sempre lança erro ou roda para sempre), o tipo de retorno é never.

Arrow functions e function expressions

Arrow functions e function expressions recebem as mesmas anotações. O tipo de retorno vai depois da lista de parâmetros, antes do =>.

Sem os parênteses, (x, y) => { x, y } é um bloco sem return, e a função retorna undefined. As regras de tempo de execução das arrow functions (sem this próprio, sem arguments) são as mesmas do JavaScript; veja arrow functions em JavaScript.

Quando uma função é escrita inline como argumento, normalmente você nem anota os parâmetros. O TypeScript sabe o que o callback recebe a partir da função para a qual ele é passado (contextual typing): em [1, 2].map(n => n * 2), n já é number. Escrever o tipo de uma função como valor, (n: number) => string, é assunto de tipos de função.

Retornando vários valores

Uma função retorna um único valor, então retorne um objeto ou uma tupla e desestruture.

O tipo de retorno de tupla precisa da anotação. Sem ela, [a, b] é inferido como string[]: a desestruturação continua funcionando, mas o tipo deixa de dizer que há exatamente dois elementos.

Funções async

Uma função async sempre retorna uma Promise. Anote o tipo de retorno como Promise<T>, em que T é o que a função retorna internamente.

async function loadScore(id: number): Promise<number> {
  await new Promise((resolve) => setTimeout(resolve, 10));
  return id * 10;
}

async function main(): Promise<void> {
  const score = await loadScore(4); // score: number
  console.log("score", score);
}

main();

Escrever async function f(): number é um erro: The return type of an async function or method must be the global Promise<T> type. Did you mean to write 'Promise<number>'? (TS1064).

O parâmetro this

O JavaScript decide o this no momento da chamada. O TypeScript permite declarar o que o this precisa ser com um primeiro parâmetro falso chamado this. Ele é removido do JavaScript compilado, e quem chama não o passa.

interface Counter {
  count: number;
}

function increment(this: Counter, by: number): void {
  this.count += by;
}

const c = { count: 0, increment };
c.increment(2); // fine: this is c

increment(2);
// error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'Counter'.

Sem o parâmetro this, o this dentro de uma função avulsa é um any implícito, e o strict mode mostra 'this' implicitly has type 'any' because it does not have a type annotation. (TS2683). Em métodos de classe, o this já é tipado como a instância da classe, então o parâmetro é útil principalmente para funções avulsas anexadas a objetos e para callbacks que bibliotecas chamam com um this específico.

Perguntas frequentes

Como definir o tipo de retorno de uma função no TypeScript?

Escreva dois-pontos e o tipo depois da lista de parâmetros: function total(a: number, b: number): number { ... }. Em uma arrow function ele vai no mesmo lugar: const total = (a: number, b: number): number => a + b;. Se você omitir, o TypeScript infere o tipo de retorno a partir das instruções return.

Devo sempre anotar o tipo de retorno no TypeScript?

É opcional, porque o tipo de retorno é inferido. Anote em funções exportadas e em funções com vários caminhos de return: a anotação documenta o contrato, e um return errado passa a ser apontado dentro da função, e não em alguma chamada distante.

Qual é a diferença entre void e undefined no TypeScript?

void significa "quem chama não deve usar o valor de retorno". undefined é um tipo de valor concreto. Uma função declarada (): void não pode retornar um valor, mas um tipo de callback () => void aceita uma função que retorna algo, e o resultado simplesmente é ignorado. Use void para funções que não retornam nada e undefined só quando quem chama realmente compara o resultado com undefined.

Como retornar vários valores de uma função TypeScript?

Retorne um objeto ({ min: number; max: number }) ou uma tupla ([number, number]) e desestruture na chamada. Objetos são mais claros quando os valores têm significados diferentes; tuplas ficam boas para pares curtos como [value, setValue].

Qual é o tipo de retorno de uma função async no TypeScript?

Sempre uma Promise. Uma função async que retorna um number tem o tipo de retorno Promise<number>, e escrever : number nela é erro de compilação (TS1064). Uma função que não retorna nada é Promise<void>.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR