typescript gotchas: 10 common pitfalls and how to avoid them

Learn the basics of TypeScript and avoid common mistakes.

Typscript: TypeScript is a highly typed programming language that builds on JavaScript, which gives you better tooling at any scale.

10 common gotchas in typescript

  1. Type Inference Surprises

    • TypeScript infers types, but sometimes not as you expect. Always check inferred types.
    1
    2
    
    let x = null; // x: any
    let y = [0];  // y: number[]
    
  2. Any Type Leaks

    • Using any defeats the purpose of TypeScript. Avoid it unless absolutely necessary.
    1
    2
    
    let data: any = fetchData();
    // No type safety on 'data'
    
  3. Structural Typing

    • TypeScript uses structural typing, so objects with the same shape are considered compatible, even if unrelated.
    1
    2
    3
    4
    
    interface Point { x: number; y: number; }
    interface Coord { x: number; y: number; }
    const p: Point = { x: 1, y: 2 };
    const c: Coord = p; // OK
    
  4. Enums Are Not Type-Safe

    • Enums can be assigned any number, not just defined values.
    1
    2
    
    enum Status { Ready, Waiting }
    let s: Status = 123; // Allowed
    
  5. Type Assertions Don’t Convert Types

    • as Type only tells the compiler to treat a value as a type; it doesn’t actually convert it.
    1
    2
    
    let input = "123";
    let num = input as unknown as number; // No actual conversion
    
  6. Optional Properties Can Be Undefined

    • Accessing optional properties without checks can cause runtime errors.
    1
    2
    3
    4
    5
    
    interface User { name?: string }
    function greet(u: User) {
      // u.name?.toUpperCase() is safer
      console.log(u.name.toUpperCase()); // Error if name is undefined
    }
    
  7. Excess Property Checks

    • TypeScript checks for extra properties in object literals, but not when assigning to variables.
    1
    2
    3
    4
    
    interface Person { name: string }
    const p = { name: "A", age: 30 };
    let person: Person = p; // OK
    // let person: Person = { name: "A", age: 30 }; // Error
    
  8. Narrowing Doesn’t Always Work

    • Type guards may not always narrow types as expected, especially with unions.
    1
    2
    3
    4
    5
    6
    
    function print(val: string | number) {
      if (typeof val === "string") {
        // val is string
      }
      // val may still be string | number here
    }
    
  9. Third-Party Types May Be Outdated

    • Always check if @types/ packages match the library version you use.
    1
    2
    
    // npm install @types/lodash@latest
    // Check compatibility with lodash version
    
  10. Type-Only Imports Are Erased

    • Imports used only for types are removed from the output, which can cause issues if you expect runtime side effects.
    1
    2
    
    import type { Foo } from './foo'; // Only for types, removed at runtime
    import './foo'; // Ensures side effects run
    

These should be kept in mind to avoid common pitfalls when working with TypeScript!

Built with Hugo
Theme Stack designed by Jimmy