codewithjohn.dev
Published on

Type Checking in JavaScript

Table of Contents

JavaScript is dynamically typed. Unlike statically typed languages where variables have a predefined type, JavaScript variables can hold different types of data throughout their lifetime. While this freedom allows for rapid development, it can also lead to unexpected behavior if you're not careful. Type checking is essential for code safety and maintainability.

This article covers the two main operators for type checking in JavaScript: typeof and instanceof. We will discuss their features, limitations, and recommended practices for integrating them into your code.

The typeof Operator

The typeof operator is a unary operator that returns a string indicating the data type of its operand (the value it operates on). It's a handy tool for basic type checks, especially for primitive data types like numbers, strings, and booleans.

Here's the syntax:

typeof operand
  • 'number': For numerical values (e.g., typeof 42 evaluates to "number")
  • 'string': For string values (e.g., typeof "hello" evaluates to "string")
  • 'boolean': For Boolean values (true or false) (e.g., typeof true evaluates to "boolean")
  • 'undefined': For variables declared but not assigned a value (e.g., typeof x; // x is declared but not assigned evaluates to "undefined")
  • 'symbol': For symbol values (a new primitive type introduced in ES6) (e.g., typeof Symbol("mySymbol") evaluates to "symbol")

Let's look at some examples:

let num = 10
let str = 'hello'
let bool = false
const sym = Symbol('foo')

console.log(typeof num) // Output: "number"
console.log(typeof str) // Output: "string"
console.log(typeof bool) // Output: "boolean"
console.log(typeof sym) // Output: symbol
  • Undefined and Null: typeof undefined returns "undefined" and typeof null surprisingly returns "object".

    let emptyVar
    console.log(typeof emptyVar) // Outputs: "undefined"
    
    let someObject = null
    console.log(typeof someObject) // Outputs: "object"
    
    if (someObject === null) {
      console.log('The variable is null')
    }
    
  • Functions: typeof identifies functions as a distinct type: "function".

    function greet() {
      console.log('Hello!')
    }
    console.log(typeof greet) // Outputs: "function"
    

While typeof is useful for primitive types, it has limitations:

  • Arrays: In JavaScript, arrays are technically objects. So, typeof [] will return "object" This can be misleading if you specifically want to check for arrays.

    let numbers = [1, 2, 3]
    console.log(typeof numbers) // Outputs: "object"
    
  • Custom Objects: Similar to arrays, custom objects created using the object literal syntax will also be identified as "object" by typeof.

    let person = {
      name: 'Bob',
      age: 25,
    }
    console.log(typeof person) // Outputs: "object"
    

These limitations can make it difficult to precisely determine the exact type of an object using typeof alone.

The instanceof Operator:

The instanceof operator comes into play when you need to check if an object is an instance of a specific constructor function. It returns true if the object's prototype chain can be traced back to the constructor function on the right side of the operator.

Here's the syntax:

object instanceof constructor

Code Example 2: Using instanceof with Arrays

let numbers = [1, 2, 3]
console.log(numbers instanceof Array) // Outputs: true

let person = {
  name: 'Bob',
  age: 25,
}
console.log(person instanceof Object) // Outputs: true (all objects inherit from Object)

function Car(model) {
  this.model = model
}

let myCar = new Car('Tesla')
console.log(myCar instanceof Car) // Outputs: true

In this example, numbers instanceof Array evaluates to true because numbers was created using the Array constructor function. It also inherits from the Object constructor, so numbers instanceof Object is also true.

Conclusion

While JavaScript's flexibility offers freedom in development, type checking with typeof and instanceof operators helps catch errors early, improves code readability, and ensures maintainability. Though typeof has limitations with arrays and symbols, and instanceof requires knowing the constructor, using them strategically strengthens your JavaScript applications.