Tipar funciones básicas

En esta clase vamos a lo esencial de TypeScript cuando trabajas con funciones: tipar parámetros, tipar el retorno y entender hasta dónde llega la inferencia. También veremos casos muy comunes como parámetros opcionales, valores por defecto, rest parameters y cómo extraer un tipo de función para reutilizar contratos.

Tipar parámetros y retorno

Para tipar una función, tipamos cada parámetro con : y su tipo. Y si queremos especificar el tipo de retorno, lo indicamos después de los paréntesis con : TipoRetorno.

function sumar(a: number, b: number): number {
  return a + b
}

La inferencia de TypeScript (y cuándo aprovecharla)

TypeScript puede inferir muchas cosas, pero no hace magia: si no tipas los parámetros, no siempre puede saber qué son (y con + puede ser número o string).

Una buena regla práctica:

  • Si TypeScript puede inferir bien, déjale hacerlo.
  • Si estás definiendo un contrato importante, tipa explícitamente para evitar sorpresas.

Por ejemplo, si cambias sin querer la lógica y el retorno se vuelve string, el contrato puede cambiar sin darte cuenta si no lo fijaste.

Parámetros opcionales con ?

Si un parámetro es opcional, se marca con ?. Eso implica que puede ser del tipo declarado o undefined.

function saludar(nombre: string, apellido?: string) {
  if (apellido) return `Hola ${nombre} ${apellido}`
  return `Hola ${nombre}`
}

apellido?: string es equivalente a apellido: string | undefined, pero mucho más cómodo de leer.

Valores por defecto

Un parámetro con valor por defecto ya es opcional de forma implícita, así que no se mezcla con ?.

function crearUsuario(nombre: string, rol: string = 'admin') {
  return { nombre, rol }
}

Esto está bien. Pero esto no se puede (no tiene sentido que sea opcional si siempre tendrá valor):

// function crearUsuario(nombre: string, rol?: string = 'admin') {} // Error

Rest parameters (parámetros variables)

Cuando no sabes cuántos argumentos te van a pasar, usas ... y los tipas como un array.

function sumarTodos(...numeros: number[]) {
  return numeros.reduce((acc, n) => acc + n, 0)
}

sumarTodos(1, 2, 3)    // 6
sumarTodos(10, 20)      // 30
sumarTodos()            // 0

Funciones que no retornan: void (y el caso de never)

Hay funciones que “no devuelven nada” (por ejemplo, solo hacen un console.log) y se tipan como void.

function logMensaje(msg: string): void {
  console.log(msg)
}

Y si una función nunca termina normalmente (por ejemplo, siempre lanza un error), se tipa como never.

function crash(mensaje: string): never {
  throw new Error(mensaje)
}

Tipos de función (Function Types) para reutilizar contratos

En vez de repetir tipos en cada función, puedes extraer el “contrato” a un tipo y reutilizarlo.

type OperacionMatematica = (a: number, b: number) => number

const dividir: OperacionMatematica = (a, b) => a / b
const restar: OperacionMatematica = (a, b) => a - b
const multiplicar: OperacionMatematica = (a, b) => a * b

Así te aseguras de que todas las funciones que representen una operación matemática siguen exactamente el mismo contrato.

Resumen

  • Tipar parámetros es clave porque la inferencia no siempre alcanza.
  • El retorno se tipa con ): TipoRetorno.
  • ? convierte el parámetro en Tipo | undefined.
  • Valor por defecto implica “opcional implícito”, no se combina con ?.
  • ...rest se tipa como array.
  • void para funciones sin retorno útil, never para las que no terminan.
  • Los function types ayudan a reutilizar contratos y mantener consistencia.