Tuplas en TypeScript

En esta clase vemos tuplas: un tipo especial de array donde el orden importa y cada posición tiene un tipo definido. Es justo lo que pasa con useState en React, que devuelve una tupla con dos posiciones.

¿Qué es una tupla?

Una tupla es un array con:

  • Longitud fija (o parcialmente fija si usamos rest)
  • Tipos por posición
  • Orden significativo

Ejemplo: una “persona” como [nombre, edad]:

type Persona = [string, number]

const persona: Persona = ['midudev', 40]

const nombre = persona[0] // string
const edad = persona[1]   // number

Lo potente es que TypeScript sabe que persona[0] es string y persona[1] es number.

Casos típicos de tuplas

Coordenadas

type Coordenadas = [number, number]

const coords: Coordenadas = [41.327, 2.095] // lat, lng

Colores RGB

type RGB = [number, number, number]

const rojo: RGB = [255, 0, 0]

Rangos (min, max)

type RangoEdad = [number, number]

const permitido: RangoEdad = [18, 65]

Estos ejemplos funcionan bien cuando el significado viene del orden.

Tuplas como retorno de funciones (el caso useState)

Una tupla encaja perfecto cuando una función devuelve “varias cosas” con posiciones fijas:

type SetState<T> = (value: T) => void
type UseStateReturn<T> = [T, SetState<T>]

declare function useState<T>(initial: T): UseStateReturn<T>

const [contador, setContador] = useState(0)

Primera posición: el estado. Segunda: la función para actualizarlo.

Tuplas con rest elements

También podemos decir: “primero un string y después todos los números que quieras”.

type StringYMuchosNumeros = [string, ...number[]]

const datos: StringYMuchosNumeros = ['texto', 1, 2, 3, 4]

const [text, firstNumber, ...restOfNumbers] = datos
// text: string
// firstNumber: number
// restOfNumbers: number[]

Esto hace la desestructuración súper cómoda y bien tipada.

”No me entero”: nombra las posiciones

Si te pasa lo de ver [number, number] y pensar “¿cuál era cuál?”, puedes nombrar los elementos de la tupla para que TypeScript lo use como documentación:

type Coordenadas = [latitud: number, longitud: number]
type Rango = [min: number, max: number]
type Persona = [nombre: string, edad: number]

No cambia el runtime, pero mejora la legibilidad y el hover del editor.

Tuplas readonly

Si quieres evitar que alguien modifique la tupla, puedes marcarla como solo lectura:

type Config = readonly [server: string, puerto: number, usaSSL: boolean]

const config: Config = ['localhost', 5432, true]

// config[1] = 9999 // Error: readonly

Ideal para configuraciones o datos que no deberían cambiar.

Cuándo usar tuplas (y cuándo no)

Úsalas cuando:

  • El orden tiene significado real.
  • La estructura es corta y fija (2-4 elementos suele ser lo más legible).
  • Quieres un retorno múltiple tipo [valor, setter].

Mejor un objeto cuando:

  • Hay muchas propiedades.
  • Te importa más el “nombre” que el orden.
  • La estructura crece o cambia a menudo.

Mini ejercicios

  • Crea un tipo HTTPResponse como tupla: [status: number, body: string] y tipa una función que lo devuelva.
  • Crea un tipo RGBA como tupla de 4 números.
  • Crea un tipo LogEntry como [message: string, ...tags: string[]] y desestructúralo en variables.

Resumen

  • Las tuplas son arrays con longitud fija y tipos por posición.
  • Puedes nombrar las posiciones para mejorar la legibilidad.
  • Los rest elements (...number[]) permiten tuplas con parte variable.
  • Marca como readonly las tuplas que no deben mutarse.
  • Si la estructura crece o el orden no importa, usa un objeto en su lugar.