TypeScript

A Comprehensive Guide to the typeOf Operator in Typescript

Picture of me, Omari
Omari Thompson-Edwards
Tue Mar 05 2024 4 min

In JavaScript (and TypeScript), "typeof" is a type-checking operator. It returns a string indicating the type of whatever operand you pass to it. TypeScript still includes this operator, but extends it to be usable in a type context to get the TypeScript type of a variable.

JavaScript.

For JavaScript, "typeof" runs at runtime, meaning it exists in JavaScript-land, after all the TypeScript has been compiled away. Here's all the possible values:

string"string"
number"number"
bigint"bigint"
boolean"boolean"
undefined"undefined
symbol"symbol"
null"object"
function"function"
Any other object"object"

So most of this you might expect, but some things might raise some flags.

typeof null === "object".

Why doesn't the operator return "null" for null? This is a legacy holdover from quite literally the first implementation of JavaScript. The short version is in the first version of JavaScript, values were represented by a number to represent the type, and a value. The type tag for objects for example was 0. null was represented as the NULL pointer (0x00 in most platforms). This means when read as a type tag, for example if using the "typeof" operator, you'd get the same result as an object.

I'm sorry to inform you, but there's no change of this getting changed in the near future - a proposal was made, but it was rejected.

Arrays.

Arrays under the hood are just objects in JavaScript. If you do want to check if something is an array, you can use the following method:

const myArray = [1, 7, 3, 8];
console.log(typeof myArray); //object :(
console.log(Array.isArray(myArray)); // true :)

Where's every other type I've created?

That's an exhaustive list of types. At runtime, the "typeof" operator can't return anything else. This means that you can't use the operator to do anything with your TypeScript types. something like this won't work for example:

type Fruit = {
    name: string;
};

type Vegetable = {
    name: string;
};

function bothFruitOrVegetable(
    fruitOrVegetable1: Fruit | Vegetable,
    fruitOrVegetable2: Fruit | Vegetable
) {
    return typeof fruitOrVegetable1 === typeof fruitOrVegetable2;
}

They'll always be the same type according to the operator - "object".

This goes back to earlier - TypeScript types don't exist at runtime.

So when is the operator useful for TypeScript?

Type Narrowing.

TypeScript can use the operator for type narrowing. Let's take a look by building a concatenation function. Our function will join strings or arrays, but in order to do that, we need to know if we're dealing with a pair of strings or a pair of arrays.

We'll deal with the first case, strings:

function concat(a: string | unknown[], b: string | unknown[]) {
    if (typeof a === 'string' && typeof b === 'string') {
        return a + b;
    }
}

TypeScript is smart enough to use the typeof operator here to know if we're inside that if statement, then a and b must have been strings.

Just like before we can't use the operator to check for arrays, but we can use "Array.isArray()":

function concat(a: string | unknown[], b: string | unknown[]) {
    if (typeof a === 'string' && typeof b === 'string') {
        return a + b;
    }
    if (Array.isArray(a) && Array.isArray(b)) {
        return [...a, ...b];
    }
}

And again, TypeScript we can only be in that if statement if the condition was true, and the condition is that both a and b are arrays.

Extracting Types.

You can also use the operator to get the type of an object in a TypeScript context. What does that mean? Let's take a look at the difference with an example:

type ShoppingList = {
    fruitAndVegetables: string[];
    meat: string[];
    dairy: string[]; //etc
};

const shoppingList: ShoppingList = {
    fruitAndVegetables: [],
    meat: [],
    dairy: [],
};

console.log('Shopping List:', typeof shoppingList);
//Shopping List: object
type ShoppingList2 = typeof shoppingList;
/*
    type ShoppingList2 = {
    fruitAndVegetables: string[];
    meat: string[];
    dairy: string[];
}
*/

In a runtime context, the type of our shopping list is an object. That's the result you'll get if you use the operator in runtime expressions. TypeScript also lets you use the operator to get the type of the object to use in a type context. Something important to note is that you can only use this expression on variables or their properties - anything else won't work.

Conclusion.

So to sum everything up:

  • In JavaScript, "typeof" returns a string that represents the type of a variable
  • TypeScript extends the operator by allowing you to use it to extract the type of a variable for TypeScript types.

Thanks for reading, hopefully, this was a useful guide to the operator and its uses in both TypeScript and JavaScript. If you liked this article, why not shoot me a following Twitter?

read more.

Me
Hey, I'm Omari 👋

I'm a full-stack developer from the UK. I'm currently looking for graduate and freelance software engineering roles, so if you liked this article, feel free to reach out.