TypeScript de Cero a Experto / Funciones e interfaces
Tipar funciones a fondo: entradas y salidas
Las funciones son el corazón de tu código, y TypeScript las tipa con precisión quirúrgica: qué recibe cada parámetro, cuáles son opcionales, cuál es el valor de retorno. Dominar esto es escribir contratos claros —el que llama sabe exactamente qué darle y qué esperar, sin leer el cuerpo.
La ficha técnica de una máquina
Parámetros: obligatorios, opcionales, por defecto, rest
TypeScript distingue cuatro formas de recibir datos, y cada una comunica una intención:
// OBLIGATORIOS: hay que pasarlos, en orden
function crear(nombre: string, valor: number) { /* ... */ }
// OPCIONAL con ?: puede faltar (su tipo es T | undefined). Va DESPUÉS de los obligatorios
function saludar(nombre: string, titulo?: string) {
return titulo ? titulo + " " + nombre : nombre; // manejas el undefined
}
saludar("Sara"); // ✓
saludar("Sara", "Dra."); // ✓
// POR DEFECTO: si no lo pasas, toma el valor dado (y TS infiere el tipo del default)
function repetir(texto: string, veces = 1) { // veces es number, inferido
return texto.repeat(veces);
}
// REST: cantidad variable, todos del mismo tipo → un array tipado
function sumar(...numeros: number[]): number {
return numeros.reduce((s, n) => s + n, 0);
}
sumar(1, 2, 3, 4); // numeros = [1,2,3,4]Tres reglas que evitan errores: los opcionales van SIEMPRE después de los obligatorios (si no, ¿cómo sabría TS cuál omitiste?); un parámetro por defecto infiere su tipo del valor dado; y el rest recoge "el resto" en un array tipado. Con esto cubres cualquier firma que necesites.
El retorno: anotarlo o dejarlo inferir
TS infiere el retorno perfectamente, pero anotarlo tiene un valor: hace que un error se marque DENTRO de la función (donde está el bug) y no en quien la llama:
// retorno inferido (number): cómodo para funciones internas
function doble(n: number) {
return n * 2;
}
// retorno anotado: un contrato explícito; si el cuerpo no cumple, error AQUÍ
function precioFinal(precio: number, descuento: number): number {
return precio - descuento; // si devolvieras un string, TS lo marca en esta línea
}
// void: la función NO devuelve nada útil (efecto secundario: log, guardar, pintar)
function registrar(mensaje: string): void {
console.log("[log]", mensaje);
// no hay return con valor
}void es el tipo de "no devuelvo nada que debas usar" —típico de funciones que
existen por su efecto (imprimir, guardar, disparar un evento). Los equipos suelen
anotar el retorno de las funciones EXPORTADAS (contrato público) y dejar inferir
las internas. Tú elige, pero sé consistente.
La firma como tipo reutilizable
Puedes guardar la FORMA de una función en un tipo —clave para tipar callbacks y parámetros que son funciones:
// un tipo que describe "una función que toma dos números y devuelve uno"
type Operacion = (a: number, b: number) => number;
// ahora tipas variables/parámetros con esa firma:
const suma: Operacion = (a, b) => a + b; // a y b se infieren como number
const resta: Operacion = (a, b) => a - b;
// y una función que RECIBE una operación (orden superior, del SC-02):
function aplicar(a: number, b: number, op: Operacion): number {
return op(a, b);
}
console.log(aplicar(10, 3, suma)); // 13
console.log(aplicar(10, 3, resta)); // 7La sintaxis (a: number, b: number) => number describe una función como tipo:
sus parámetros y su retorno, con la flecha en medio. Fíjate que al asignar const suma: Operacion = (a, b) => ..., ya NO anotas a ni b —TS los infiere del tipo
Operacion. Ese tipo-función es la pieza que hace posible tipar los callbacks y
las funciones de orden superior que tanto usaste en JavaScript.
¿Por qué esta función da error? function saludar(titulo?: string, nombre: string) { ... }
Mini-reto
Tipa funciones de verdad: 1) escribe type Validador = (valor: number) => boolean
y crea dos validadores (esPositivo, esEntero); 2) escribe function cumpleTodos(valor: number, ...validadores: Validador[]): boolean que use rest
para aceptar cualquier cantidad de validadores y devuelva true si el valor los
cumple todos (every); 3) pruébala. Acabas de tipar una función que recibe otras
funciones —el patrón que sostiene medio JavaScript funcional.
Qué sigue
Tipaste funciones que reciben funciones. La próxima lección profundiza en ese
patrón: tipar CALLBACKS con precisión —los de map, filter, los event
listeners— para que el TypeScript de tu código funcional y de tus eventos sea tan
seguro como el resto.