javascripttypescripttypes

Why is typescript not restricting the type alias to adhere to it structure?


Screenshot of Code snippet

So, here is my code so as you can see newUser has got its property from User and is also a constant. So why does Typescript let it use the push function of arrays to push a boolean value - "True" inside the type alias when the structure restrict its?


Solution

  • Why is TypeScript not restricting the type alias to adhere to its structure?

    In the following TypeScript code:

    type User = [number, string];
    const newUser: User = [112, "example@google.com"];
    
    newUser[1] = "hc.com";     // ✅ Allowed
    newUser.push(true);        // ⚠️ No error?!
    

    I expected TypeScript to prevent newUser.push(true) since User is defined as a tuple of [number, string]. However, TypeScript allows this due to the mutable nature of tuples.

    What's going on?

    Tuples in TypeScript are essentially special arrays. At runtime, there's no real distinction between an array and a tuple — both are JavaScript arrays. Unless specified otherwise, tuples are mutable, and methods like .push() are available.

    So newUser.push(true) compiles because:

    TypeScript treats the tuple as an array.

    .push() exists on arrays.

    TypeScript doesn't strictly enforce the tuple's length or element types for mutations unless stricter typing is applied.

    How to enforce stricter tuple rules

    1. Make the tuple readonly: This prevents any modification, including .push() and element reassignment.
    type User = readonly [number, string];
    
    1. Use as const for literals: This creates an immutable tuple from the start.
    const newUser = [112, "example@google.com"] as const;
    

    This will infer the type as readonly [112, "example@google.com"] and block any mutation attempts.