Skip to main content

Command Palette

Search for a command to run...

JavaScript Doesn’t Have Tuples, Here’s How to Mimic Them Safely

Published
3 min read
JavaScript Doesn’t Have Tuples, Here’s How to Mimic Them Safely
A

Full-Stack Developer & Tech Writer specializing in Python (Django, FastAPI, Flask) and JavaScript (React, Next.js, Node.js). I build fast, scalable web apps and share practical insights on backend architecture, frontend performance, APIs, and Web3 integration. Available for freelance and remote roles.

If you’re a JavaScript developer, you probably know the two most common ways to store data: arrays and objects.

  • Arrays → Ordered, iterable lists

  • Objects → Named key-value pairs

But sometimes you need something in between: a small, fixed-size group of related values where order matters and accidental mutation could break your code.

This is where tuple-like thinking becomes valuable.

⚠️ JavaScript does not have built-in tuples like Python or Rust.
But you can mimic tuple behavior with arrays, Object.freeze(), and TypeScript.

Arrays: Flexible and Dynamic

Arrays in JavaScript are objects optimized for sequential data:

const fruits = ["apple", "banana", "cherry"];
fruits.push("mango");        // adds to the end
fruits[1] = "blueberry";     // updates an element
console.log(fruits);         // ["apple", "blueberry", "cherry", "mango"]

Under the hood:

  • Arrays are objects with numeric keys and a length property

  • Indices don’t have to be contiguous (sparse arrays are allowed)

  • Keys are technically strings ("0", "1", …), but JS optimizes them

Use arrays for: dynamic collections, variable-length data, frequent updates
Avoid arrays for: fixed-size, order-critical data

Creating Tuple-Like Behavior

To create a fixed, ordered, immutable set, combine:

  1. Array → preserves order

  2. Object.freeze() → prevents mutation

const point = Object.freeze([10, 20]);

point[0] = 99; // ❌ fails silently in non-strict mode, throws TypeError in strict mode
console.log(point); // [10, 20]

Now point behaves like a Python tuple, but the immutability is enforced at runtime.

How Object.freeze() Works

When you freeze an object or array, JS:

  • Makes it non-extensible (no new properties can be added)

  • Marks properties non-writable and non-configurable

  • Prevents reassignment or deletion

Important: Freeze is shallow nested objects remain mutable unless frozen separately.

const config = Object.freeze({
  api: Object.freeze({ url: "https://example.com" }),
  retries: 3
});

// config.retries = 5; // ❌ fails
config.api.url = "https://new.com"; // ✅ still allowed unless api is frozen

For deep immutability, use a recursive function:

function deepFreeze(obj) {
  Object.freeze(obj);
  for (const key of Object.keys(obj)) {
    if (typeof obj[key] === "object" && obj[key] !== null) {
      deepFreeze(obj[key]);
    }
  }
}

Real-World Example: Game Development

const START_POSITION = Object.freeze([0, 0]); 
const FINISH_POSITION = Object.freeze([10, 15]);

Frozen arrays prevent accidental mutation:

function movePlayer(player) {
  START_POSITION[0] += 1; // ❌ fails because START_POSITION is frozen
}

When to Use Arrays, Objects, or Tuple-Like Arrays

Use CaseBest ChoiceWhy
List of unknown lengthArrayIdeal for iteration and dynamic growth
Named data structureObjectEasier to read, descriptive keys
Fixed-size ordered setFrozen ArrayMaintains order and prevents accidental mutation
Strong compile-time safetyTypeScript TupleEnforces length and element types at compile time

Tuple Thinking in Practice

  • Arrays → when order matters

  • Objects → when names matter

  • Tuple-like arrays → when both order and immutability matter

  • TypeScript readonly tuples → maximum compile-time safety

const user: readonly [string, number, boolean] = ["Alice", 25, true];
// user[1] = 30; // ❌ Compile-time error

Key Takeaways

✅ JavaScript arrays aren’t tuples, but can act like them
✅ Use Object.freeze() or deepFreeze() for runtime immutability
✅ Choose the right data shape: list (array), record (object), tuple (frozen array)
✅ TypeScript readonly tuples enforce immutability and length at compile-time
✅ Preventing mutation early reduces subtle bugs

More from this blog

A

Anik Sikder - The Dev Loop

21 posts

Practical tips on building fast, scalable web apps using Python, JavaScript, and Web3. Learn how I turn ideas into reliable, production-ready digital products.