Primitive Types, Arrays & Tuples

11 questions found

What are TypeScript's basic primitive types, and how do you annotate a variable with one?

Beginner
TypeScript's core primitives are string, number, boolean, null, undefined, symbol, and bigint — annotate a variable using a colon followed by the type name after its identifier.
let name: string = 'Sam';
let age: number = 30;
let isActive: boolean = true;
Real-world example Explicitly annotating a function parameter's expected primitive type to catch incorrect calls at compile time.

Common follow-ups: Why does TypeScript recommend lowercase 'string'/'number'/'boolean' instead of the capitalized 'String'/'Number'/'Boolean' wrapper object types?

Never Unknown & Void Types

How do you type an array of a specific element type, and what are the two equivalent syntaxes?

Beginner
Use either `Type[]` (more common, especially for simple types) or the generic `Array<Type>` syntax (sometimes preferred for more complex or nested generic types, for readability) — both are functionally identical.
let scores: number[] = [90, 85, 78];
let names: Array<string> = ['Sam', 'Alex'];
// Array<Array<number>> can be more readable than number[][]
Real-world example Typing a function parameter that accepts a list of user objects or numeric scores.

Common follow-ups: Which syntax is generally preferred by style guides, and does it matter functionally?

Generics

What is a tuple, and how does it differ from a regular array type?

Beginner
A tuple is a fixed-LENGTH array where each position has its own SPECIFIC type, unlike a regular array type where every element must share the same single type — tuples are declared with square brackets listing each position's type in order.
let point: [number, number] = [3, 4]; // exactly two numbers
let entry: [string, number] = ['age', 30]; // first is string, second is number
// let bad: [number, number] = [1, 2, 3]; // Error: too many elements
Real-world example Typing a coordinate pair, a key-value entry, or a fixed-shape function return like [value, error].

Common follow-ups: How does destructuring a tuple differ from destructuring a regular array in terms of type safety?

Destructuring Spread & Rest

How do you make a tuple element optional, and how does that affect the tuple's minimum required length?

Intermediate
Add '?' after a tuple element's type, similar to optional function parameters — optional elements must come after all required elements, and TypeScript correctly tracks that the tuple's minimum length no longer includes the optional trailing elements.
type Point = [x: number, y: number, z?: number];
const p2d: Point = [3, 4];       // OK, z omitted
const p3d: Point = [3, 4, 5];    // OK, z included
Real-world example Typing a 2D-or-3D coordinate tuple where the z-axis is only sometimes relevant.

Common follow-ups: Can you mix optional tuple elements with a rest element in the same tuple type?

Function Types Overloads & Optional/Default Parameters

How do labeled tuple elements improve readability and editor tooling compared to unlabeled tuples?

Intermediate
Adding a name before each element's type (like `[x: number, y: number]`) doesn't change runtime behavior at all, but significantly improves editor autocomplete/hover tooltips and function signature readability — especially valuable for tuples used as function parameter lists or return values with multiple positions.
function move([deltaX, deltaY]: [x: number, y: number]) {
  console.log(`Moving by ${deltaX}, ${deltaY}`);
}
// hovering the tuple type in an editor now shows 'x' and 'y' labels instead of just 'number, number'
Real-world example Improving the developer experience of a utility function's tuple-typed return value, like a custom useToggle() hook returning [value, toggle].

Common follow-ups: Do labeled tuple elements require ALL elements in the tuple to be labeled, or can you mix labeled and unlabeled?

Generics

How does a rest element work within a tuple type, like `[string, ...number[]]`?

Intermediate
A tuple can end with a rest element (using '...Type[]') to require a FIXED set of leading elements of specific types, followed by any number (including zero) of additional elements all sharing the rest element's type — combining tuple precision with array flexibility.
type StringThenNumbers = [string, ...number[]];
const a: StringThenNumbers = ['label'];           // OK, zero numbers
const b: StringThenNumbers = ['label', 1, 2, 3];  // OK, three numbers
Real-world example Typing a function's arguments where the first argument has a fixed meaning (like a format string) followed by a variable number of typed values.

Common follow-ups: Can a rest element appear at the START of a tuple instead of the end?

Function Types Overloads & Optional/Default Parameters

How does TypeScript infer a tuple type versus a regular array type from an array literal, and how do 'as const' assertions change this?

Advanced
By default, an array literal like `[1, 2]` is inferred as the wider `number[]` array type, NOT a tuple — to get a precise, fixed-length tuple type inferred automatically, apply `as const`, which locks both the literal element values AND the tuple's fixed length/readonly-ness.
const loose = [1, 2];              // inferred as number[]
const tuple = [1, 2] as const;     // inferred as readonly [1, 2] -- a precise tuple of literal values
Real-world example Getting precise literal-value tuple types for things like fixed configuration arrays or coordinate constants, without a manual type annotation.

Common follow-ups: Why does 'as const' also make the resulting tuple type readonly, and how would you get a mutable tuple with the same shape?

Readonly const Assertions & Immutability

How would you write a generic type that extracts the length of a tuple type at compile time?

Advanced
Since tuple types carry a real '.length' property whose VALUE is a specific literal number (not just 'number' like regular arrays), you can access it directly via an indexed access type on the tuple's 'length' key to extract that literal numeric type.
type TupleLength<T extends readonly unknown[]> = T['length'];
type Len = TupleLength<[string, number, boolean]>; // 3 (the literal number type, not just 'number')
Real-world example Building advanced type-level utilities (like a type-safe zip or curry function) that need to reason about a tuple's exact arity at compile time.

Common follow-ups: Does this same 'length' trick work identically for a plain array type like number[], or does it behave differently?

Generics

How do variadic tuple types (using generic rest elements) let you build type-safe function composition or concat utilities?

Advanced
Variadic tuple types let a generic rest parameter (`...T extends unknown[]`) be spread and recombined within OTHER tuple positions, preserving each individual element's specific type through operations like concatenation — enabling fully type-safe utilities that work across tuples of arbitrary, differing lengths and element types.
type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U];
type Result = Concat<[string, number], [boolean]>;
// [string, number, boolean] -- each position's specific type preserved
Real-world example Building a fully type-safe function-argument concatenation utility, like a generic curry() or partial-application helper.

Common follow-ups: How do variadic tuples enable precisely typing a generic curry() function's progressively-applied argument lists?

Generics

How does readonly interact with tuple types, and what does `readonly [number, number]` prevent compared to a mutable tuple?

Advanced
A readonly tuple prevents any mutation of its elements after creation — no reassigning an index, and critically, none of the mutating array methods (push, pop, splice, sort) are even available on its type, since they'd violate the fixed-length, immutable contract; you can still read elements and destructure normally.
function getOrigin(): readonly [number, number] {
  return [0, 0];
}
const origin = getOrigin();
// origin[0] = 5; // Error: cannot assign to readonly tuple element
// origin.push(1); // Error: 'push' does not exist on type 'readonly [number, number]'
Real-world example Returning an immutable coordinate pair or fixed-shape result from a function where callers shouldn't be able to mutate it.

Common follow-ups: How does a readonly tuple type relate to the 'as const' assertion technique discussed earlier?

Readonly const Assertions & Immutability

Showing 1–10 of 11