HOWTO · JavaScript
Tuplas en JavaScript: arrays, objetos y TypeScript
JavaScript no tiene un tipo de tupla nativo. Use arrays, objetos, Object.freeze(), desestructuración o tuplas de TypeScript según el contrato necesario.
En esta página
JavaScript no tiene un valor de tupla nativo en tiempo de ejecución. Para un grupo corto y ordenado, como unas coordenadas, use un array y desestructúrelo. Use un objeto cuando los nombres describan mejor los datos. Si necesita impedir cambios directos en tiempo de ejecución, congele el array; si necesita comprobar una longitud fija y los tipos de sus elementos durante el desarrollo, use una tupla de TypeScript.
Usar un array para un par ordenado
Un array funciona bien como valor similar a una tupla cuando cada posición tiene un significado estable. Esta función devuelve primero el mínimo y después el máximo:
function minMax(values) {
return [Math.min(...values), Math.max(...values)];
}
const [minimum, maximum] = minMax([7, 3, 12]);
console.log(minimum, maximum);
Salida:
3 12
La desestructuración proporciona nombres locales útiles para las posiciones. Documente el orden para quien llame a la función. JavaScript no impone la longitud del array ni los tipos de los elementos, por lo que debe validar los datos externos antes de depender de ese contrato posicional.
Congelar un array solo cuando se necesite protección en tiempo de ejecución
const impide reasignar la variable, pero no modificar el array al que hace referencia. Object.freeze() congela el propio array:
"use strict";
const point = Object.freeze([48.8566, 2.3522]);
console.log(point[0], point[1], Object.isFrozen(point));
// point[0] = 0; // TypeError in strict mode
// point.push(3); // TypeError
Salida:
48.8566 2.3522 true
Object.freeze() devuelve el mismo objeto; no crea una copia. Si el array de entrada sigue perteneciendo al código que llama a la función, cópielo antes de congelarlo:
function asFrozenPoint(value) {
if (
!Array.isArray(value) ||
value.length !== 2 ||
!value.every(Number.isFinite)
) {
throw new TypeError("Expected two finite coordinates");
}
return Object.freeze([...value]);
}
El congelamiento es superficial. Impide cambiar los elementos directos, la longitud y las propiedades propias, pero los objetos anidados siguen siendo mutables:
const settings = Object.freeze([{ theme: "light" }]);
settings[0].theme = "dark";
console.log(settings[0].theme);
Salida:
dark
No describa una estructura anidada congelada superficialmente como totalmente inmutable. Una función de congelamiento profundo debe recorrer valores anidados y gestionar ciclos, por lo que solo conviene usarla cuando exista esa necesidad.
Usar un objeto cuando los nombres sean más claros
Las posiciones se vuelven frágiles cuando el valor contiene varias cadenas, booleanos, campos opcionales o campos que podrían cambiar:
function createUser() {
return { id: 42, name: "Ada", active: true };
}
const { id, name, active } = createUser();
Un array es apropiado para pares compactos y conocidos como [x, y] o las entradas [key, value] de Object.entries(). Un objeto es más seguro cuando, de otro modo, quien llama tendría que recordar qué significa cada índice.
Object.entries() ya proporciona un par posicional documentado. La desestructuración deja claras las dos posiciones en el lugar donde se usan:
for (const [key, value] of Object.entries({ theme: "light" })) {
console.log(`${key}: ${value}`);
}
Salida:
theme: light
Usar TypeScript para comprobar el contrato de la tupla
TypeScript puede expresar la longitud, el orden y los tipos de los elementos:
const point: readonly [number, number] = [48.8566, 2.3522];
readonly impide escrituras en el código TypeScript. Tras la compilación, el valor sigue siendo un array normal de JavaScript y no queda congelado en tiempo de ejecución. Combine una tupla de TypeScript con Object.freeze() únicamente cuando necesite tanto comprobación estática como protección en ejecución.
Resumen
Los arrays de JavaScript pueden usarse como tuplas por convención y desestructurarse con facilidad. Elija objetos para campos con nombre, Object.freeze() para protección superficial en ejecución y tuplas de TypeScript para comprobar estáticamente la longitud y los tipos.