TypeScript: Tipos de função no TypeScript
Última atualização: 2026-08-26
As funções são um conceito fundamental do JavaScript, e o TypeScript adiciona um sistema de tipos abrangente aos parâmetros e valores de retorno das funções — garantindo que as “entradas” e “saídas” de uma função sejam claramente definidas.
1. Anotações de tipo de função
(1) Tipos de parâmetros e de valores de retorno
function add(a: number, b: number): number {
return a + b;
}
let result = add(1, 2); // result Inferred as number
// add("1", "2"); // ❌ Parameter types do not match
// add(1); // ❌ Insufficient number of parameters
(2) Inferência do tipo de retorno
O TypeScript pode inferir o tipo de retorno com base na instrução return, mas recomenda-se especificá-lo explicitamente:
// Return Type Inference——Can be inferred, but not recommended(It's easy to make mistakes when deriving large functions)
function multiply(a: number, b: number) {
return a * b; // Inference Return number
}
// Explicit Annotation——Recommendations(Purpose of the Document + Compile-time errors)
function divide(a: number, b: number): number {
if (b === 0) throw new Error("The divisor cannot be zero.");
return a / b;
}
(3) void tipo de retorno
Use void quando uma função não tiver valor de retorno:
function log(message: string): void {
console.log(message);
// None return Statement,Or return; —— All of them void
}
(4) nunca retorna um valor
Use never quando uma função nunca retornar um valor — ela lançará uma exceção ou entrará em um laço infinito:
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) { }
}
| Tipo de retorno | Significado |
|---|---|
void |
A função foi executada normalmente, mas não retornou um valor |
never |
A função nunca termina (lança uma exceção ou entra em um laço infinito) |
▶ Exemplo: Funções utilitárias tipadas
function clamp(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max);
}
function formatCurrency(amount: number, symbol: string = "¥"): string {
return symbol + amount.toFixed(2);
}
console.log(clamp(150, 0, 100)); // 100
console.log(clamp(-5, 0, 100)); // 0
console.log(clamp(50, 0, 100)); // 50
console.log(formatCurrency(99.5)); // ¥99.50
console.log(formatCurrency(42, "$")); // $42.00
Saída:
100
0
50
¥99.50
$42.00
2. Parâmetros opcionais e parâmetros padrão
(1) Parâmetro opcional ?
function greet(name: string, title?: string): string {
if (title) {
return `${title} ${name}`;
}
return `Hello,${name}`;
}
console.log(greet("Charlie")); // "Hello,Charlie"
console.log(greet("Charlie", "Engineer")); // "Engineer Charlie"
function greet(title?: string, name: string) resultará em um erro.
(2) Parâmetros padrão
function createUser(name: string, role: string = "viewer", active: boolean = true): string {
return `${name},Characters:${role},${active ? "Active" : "Not activated"}`;
}
console.log(createUser("Charlie")); // Charlie,Characters:viewer,Active
console.log(createUser("Diana", "editor")); // Diana,Characters:editor,Active
console.log(createUser("Eric", "admin", false)); // Eric,Characters:admin,Not activated
(3) Parâmetros opcionais x parâmetros padrão
| Recurso | Parâmetro opcional title?: string |
Parâmetro padrão role: string = "viewer" |
|---|---|---|
| Quando chamado | Opcional; o valor é indefinido | Opcional; o valor é o padrão |
| Tipo | string | undefined |
string (não a união indefinida) |
| Recomendação | O valor pode, de fato, ser indefinido | Na maioria dos casos, é melhor definir um valor padrão razoável |
3. Parâmetros restantes
Use a sintaxe ... para reunir os parâmetros restantes em uma matriz:
function sum(first: number, ...rest: number[]): number {
return rest.reduce((total, n) => total + n, first);
}
console.log(sum(1)); // 1
console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3, 4)); // 10
(1) Os demais parâmetros devem ser do tipo array
function logAll(prefix: string, ...messages: string[]): void {
messages.forEach(msg => console.log(`${prefix}: ${msg}`));
}
logAll("DEBUG", "Start the service", "Connect to the Database", "Ready");
Saída:
DEBUG: Start the service
DEBUG: Connect to the Database
DEBUG: Ready
4. Expressões do tipo função
As funções também podem ser passadas por valor — nesse caso, utiliza-se uma expressão de tipo de função para especificar o tipo:
(1) Os aliases de tipo definem tipos de função
type MathOperation = (a: number, b: number) => number;
let add: MathOperation = (a, b) => a + b;
let subtract: MathOperation = (a, b) => a - b;
let multiply: MathOperation = (a, b) => a * b;
console.log(add(10, 5)); // 15
console.log(subtract(10, 5)); // 5
console.log(multiply(10, 5)); // 50
(2) Tipos de funções de retorno de chamada
O uso mais comum dos tipos de função — descrever a assinatura de uma função de retorno de chamada:
function fetchData(url: string, onSuccess: (data: string) => void, onError: (error: Error) => void): void {
// Simulating Asynchronous Operations
if (url.startsWith("https://")) {
onSuccess("Data loaded successfully");
} else {
onError(new Error("Supports only HTTPS"));
}
}
fetchData(
"https://api.example.com",
data => console.log(data), // ✅ (data: string) => void
error => console.log(error.message) // ✅ (error: Error) => void
);
(3) Definição de tipos de função por meio de interfaces
interface Comparator {
(a: number, b: number): number;
}
let ascending: Comparator = (a, b) => a - b;
let descending: Comparator = (a, b) => b - a;
let nums = [3, 1, 4, 1, 5];
console.log([...nums].sort(ascending)); // [1, 1, 3, 4, 5]
console.log([...nums].sort(descending)); // [5, 4, 3, 1, 1]
5. Sobrecarga de funções
A sobrecarga de funções permite que um único nome de função suporte diferentes combinações de tipos de argumentos — a sobrecarga no TypeScript segue o padrão “declaração + implementação”:
(1) Sintaxe básica
// Overloaded Signatures——Describe the return type for each parameter combination
function format(value: number): string;
function format(value: string): string;
function format(value: Date): string;
// Implementing Signatures——Must be compatible with all overloaded signatures
function format(value: number | string | Date): string {
if (typeof value === "number") {
return value.toFixed(2);
} else if (typeof value === "string") {
return value.trim();
} else {
return value.toISOString();
}
}
console.log(format(3.14)); // "3.14"
console.log(format(" hello ")); // "hello"
console.log(format(new Date())); // "2024-..."
(2) Ordem de sobrecarga
O TypeScript compara métodos sobrecarregados na ordem em que são declarados, de cima para baixo — portanto, as sobrecargas mais específicas devem ser colocadas primeiro:
// ✅ Correct Order——The specifics come first
function process(value: string): string;
function process(value: any): unknown;
// ❌ Incorrect Order——any Matches all parameters,The overloaded version that comes later will never be called.
// function process(value: any): unknown;
// function process(value: string): string;
▶ Exemplo: Sobrecarga para implementar o tratamento de eventos com segurança de tipos
function on(event: "click", handler: (x: number, y: number) => void): void;
function on(event: "keydown", handler: (key: string) => void): void;
function on(event: string, handler: Function): void {
console.log(`Registration Event:${event}`);
// Implementation details omitted...
}
// Automatically determines the correct parameter types upon invocation
on("click", (x, y) => {
console.log(`Click here:(${x}, ${y})`); // x, y Inferred as number
});
on("keydown", (key) => {
console.log(`Press the button:${key}`); // key Inferred as string
});
Saída:
// Executed successfully
6. Tipos de funções-seta
(1) Anotações de tipo para funções-seta
const add = (a: number, b: number): number => a + b;
// When acting as a callback,Parameter types can usually be inferred
const nums = [1, 2, 3];
const doubled = nums.map(n => n * 2); // n Inferred as number
const asStrings = nums.map(n => String(n)); // n Inferred as number
(2) Funções-seta e this
As funções-seta não definem seu próprio this — elas herdam o this externo:
class Timer {
seconds = 0;
start() {
// Arrow Functions——this Orientation Timer Examples
setInterval(() => {
this.seconds++;
console.log(`${this.seconds}s`);
}, 1000);
}
startBroken() {
// Ordinary Functions——this Points to the global or undefined(Strict Mode)
setInterval(function () {
// this.seconds++; // ❌ Runtime this No Timer
}, 1000);
}
}
▶ Exemplo: Parâmetros restantes e sobrecarga de funções
// Rest parameters — collecting variable arguments
function log(context: string, ...messages: string[]): void {
console.log(`[${context}] ${messages.join(", ")}`);
}
log("App", "started", "initialized", "ready");
// [App] started, initialized, ready
// Function overloads — different return types per signature
function parse(input: string): Date;
function parse(input: number): Date;
function parse(input: string | number): Date {
return typeof input === "string"
? new Date(input)
: new Date(input);
}
let fromStr = parse("2024-01-01");
let fromNum = parse(1704067200000);
console.log(fromStr.toISOString()); // "2024-01-01T00:00:00.000Z"
Saída:
[App] started, initialized, ready
2024-01-01T00:00:00.000Z
❓ Perguntas Frequentes
P: Os tipos de retorno das funções devem ser especificados explicitamente? R: Recomenda-se especificá-los. Embora o TypeScript possa inferi-los, a especificação explícita oferece três benefícios: (1) Documentação — o tipo de retorno fica imediatamente claro; (2) Prevenção contra o retorno acidental do tipo errado; (3) Melhor localização de erros — os erros são relatados na assinatura da função, em vez de no ponto de chamada. É possível omitir o tipo de retorno para funções curtas (de uma única linha
return), mas recomenda-se especificá-lo para funções com mais de três linhas.
P: Qual é a diferença entre os tipos de retorno
voideundefined? R:voidsignifica que “a função não se preocupa com o valor de retorno” — a função pode ou não ter uma instruçãoreturn, e quem a chama não deve usar o valor de retorno.undefinedé um tipo específico — a função retorna explicitamenteundefined. No desenvolvimento prático, todas as funções sem valor de retorno utilizamvoid.
P: Qual é a diferença entre sobrecarga de funções e parâmetros de tipo união? R: Um tipo união
function fn(x: string | number)apenas indica que “um parâmetro pode ser um desses tipos”, mas todas as combinações de parâmetros retornam o mesmo tipo. A sobrecarga permite que “diferentes combinações de parâmetros retornem tipos diferentes” — algo que os tipos de união não conseguem fazer. Se os tipos dos parâmetros forem flexíveis, mas o tipo de retorno for uniforme, usar um tipo de união é mais conciso; use a sobrecarga quando forem necessários tipos de retorno diferentes.
P: É possível usar parâmetros padrão e parâmetros opcionais juntos? R: Não.
function fn(x?: string = "hi")é um erro de sintaxe — os parâmetros padrão já são considerados “opcionais” por definição, portanto não há necessidade de adicionar?.x: string = "hi"é equivalente ax?: string, mas seu valor é “hi” em vez de indefinido.
📖 Resumo
- Anotações de tipo de função: os tipos dos parâmetros devem ser anotados; recomenda-se que os tipos de retorno sejam anotados; “void” indica que não há valor de retorno, e “never” indica que a função nunca retorna.
- Use
?para parâmetros opcionais (o valor pode ser indefinido); use= defaultValuepara parâmetros padrão (é mais seguro ter um valor padrão) - Parâmetros restantes
...args: type[]Reúne os parâmetros excedentes em uma matriz - As expressões do tipo função
type Fn = (parameter) => returnValuesão usadas para descrever callbacks e funções de ordem superior - A sobrecarga de funções segue o padrão “declaração + implementação” — a declaração especifica o tipo de retorno para cada combinação de parâmetros, e a implementação deve ser compatível com todas as sobrecargas.
📝 Exercícios
- Exercício básico (Dificuldade ⭐): Escreva três funções —
add(a, b)para adição,subtract(a, b)para subtração emultiply(a, b)para multiplicação — nas quais tanto os parâmetros quanto os valores de retorno sejam do tiponumber. Use expressões do tipo função para declarar os tipos de maneira uniforme. - Problema avançado (Dificuldade ⭐⭐): Escreva uma função
buildQuery(params: Record<string, string | number | boolean>)que converta um objeto em uma string de consulta de URL. Por exemplo,{ page: 1, size: 10, active: true }→"page=1&size=10&active=true". - Desafio (Dificuldade ⭐⭐⭐): Implemente isso usando sobrecarga de funções
createElement(tag, props): quando a tag for “input”, os props devem sertype: string; quando a tag for “a”, os props devem serhref: string; e quando a tag for “div”, os props são um objeto genérico. Retorne um objeto de descrição de tipo diferente para cada caso.