Q8 of 38 · TypeScript
What are tuples in TypeScript, and when would you use them over an array or object?
Short answer
Short answer: A tuple is a fixed-length array where each position has a specific type: `[string, number]`. Use tuples for function return values where position carries meaning (like `[data, error]` from a try/catch), React-style hook returns, and CSV/structured data where index order is the contract.
Detail
A tuple type is an array where the length and the type at each index are known.
Definition: type Pair = [string, number] means index 0 is always a string, index 1 is always a number, and the array has exactly two elements. TypeScript enforces both the types and the length at assignment.
Optional elements and rest: Tuples can have optional trailing elements ([string, number?]) and rest elements ([string, ...number[]]). Named tuple elements ([name: string, age: number]) improve readability.
When to use tuples:
- [data, error] pattern: Return
[T, null]on success,[null, Error]on failure — forces callers to handle both without a thrown exception. - React-style hooks:
const [state, setState] = useState()is a tuple return. - Positional APIs: When position is the meaningful identifier (lat/lon coordinates, RGB channels).
- Small, related heterogeneous values where naming each field would be overly verbose.
When to prefer objects: When the tuple has more than 2-3 elements, when the fields have non-obvious order, or when you need to add fields over time — use a named interface instead for clarity.
// EXAMPLE
// Basic tuple
type NameAge = [string, number];
const user: NameAge = ["Alice", 30]; // ok
// const bad: NameAge = [30, "Alice"]; // Error: type mismatch
// Named elements (TypeScript 4.0+)
type Coordinate = [lat: number, lon: number];
// [data, error] pattern — no exceptions
async function safeGet<T>(url: string): Promise<[T, null] | [null, Error]> {
try {
const res = await fetch(url);
const data: T = await res.json();
return [data, null];
} catch (e) {
return [null, e instanceof Error ? e : new Error(String(e))];
}
}
const [data, err] = await safeGet<User[]>("/api/users");
if (err) { console.error(err.message); return; }
console.log(data[0].name); // TypeScript knows data is User[] here