DEV Community

Cover image for How To Check Against Custom Types In TypeScript
Onur Eren
Onur Eren

Posted on • Edited on

How To Check Against Custom Types In TypeScript

In JavaScript, you can use typeof keyword to check the type of values:

const fruit = 'apple';
console.log(typeof fruit);
// Output: 'string'

const year = 2022;
console.log(typeof year);
// Output: 'number'

const isOpen = true;
console.log(typeof isOpen);
// Output: 'boolean'

const person = {
  name: 'Thomas Anderson',
  age: 32,
};
console.log(typeof person);
// Output: 'object'
Enter fullscreen mode Exit fullscreen mode

So if you want check a value is a certain type, you can use the typeof keyword:

const fruit = 'apple';

if (typeof fruit === 'string') {
  console.log(`${fruit} is a string`);
}

const year = 2022;

if (typeof year === 'number') {
  console.log(`${year} is a number`);
}
Enter fullscreen mode Exit fullscreen mode

But, if you want to check a value is a certain type in TypeScript, the typeof keyword doesn't work the same way it works in the JavaScript examples above.

type Fruit = 'apple' | 'orange' | 'banana';

const myFruit = 'apple';

// This will NOT work ❌
if (typeof myFruit === 'Fruit') {
  console.log(`${myFruit} is a fruit`);
}
Enter fullscreen mode Exit fullscreen mode

You cannot use the typeof keyword at run-time to check for TypeScript types, because TypeScript removes type annotations, interfaces, type aliases, and other type system constructs during compilation.

So, how can you check if myFruit is the type of Fruit?

Step 1 — Type Inference

Define a Fruit type as an array of literal values and TypeScript will infer types from the values:

const fruit = ['apple', 'orange', 'banana'] as const;
type Fruit = (typeof fruit)[number];
Enter fullscreen mode Exit fullscreen mode

Step 2 — Type Guard

Use a user-defined type guard to check against your custom type:

const fruit = ['apple', 'orange', 'banana'] as const;
type Fruit = (typeof fruit)[number];

const isFruit = (x: any): x is Fruit => fruit.includes(x);
Enter fullscreen mode Exit fullscreen mode

isFruit() function will check if its argument is in the fruit array, and if so, it will narrow its argument to Fruit:

const fruit = ['apple', 'orange', 'banana'] as const;
type Fruit = (typeof fruit)[number];

const isFruit = (x: any): x is Fruit => fruit.includes(x);

const myFruit = 'apple';

// This will work ✅
if (isFruit(myFruit)) {
    console.log(`${myFruit} is a type of Fruit`);
} else {
  console.log(`${myFruit} is NOT a type of Fruit`)
}
// Output: "apple is a typeof Fruit"

Enter fullscreen mode Exit fullscreen mode

Now we can also see our type checking working, when we have a value that is not a part of our fruit array:

const fruit = ['apple', 'orange', 'banana'] as const;
type Fruit = (typeof fruit)[number];

const isFruit = (x: any): x is Fruit => fruit.includes(x);

const myFruit = 'mango';

// This will work ✅
if (isFruit(myFruit)) {
    console.log(`${myFruit} is a type of Fruit`);
} else {
  console.log(`${myFruit} is NOT a type of Fruit`)
}
// Output: "mango is NOT a typeof Fruit"
// (In reality mango is a fruit, but since it is not
// a part of our fruit array, it is NOT a type Fruit)

Enter fullscreen mode Exit fullscreen mode

In Summary

TypeScript only exists is the compile-time and it is completely discarded in the run-time.

This means you CANNOT use typeof keyword to check for custom types.

Instead, you can use type inference together with a type guard to check against a custom type.

Thank you for reading! ✌️

You can follow me on Twitter

Top comments (0)