How To Check Against Custom Types In TypeScript
Tags: webdev, typescript, javascript, react
Published: 2023-06-22 15:27:10

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

```javascript
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'
```

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

```javascript
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`);
}
```

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.

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

const myFruit = 'apple';

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

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:

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

### Step 2 — Type Guard

Use a [user-defined type guard](https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates) to check against your custom type:

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

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

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

```javascript
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"

```

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

```javascript
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)

```

### 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](https://twitter.com/itsonureren)