Typescript Tip: Safer functions with branded types.
Tags: typescript, javascript, webdev
Published: 2022-04-11 23:18:28

---
title: Typescript Tip: Safer functions with branded types.
published: true
description: When a type is too general we can use this pattern to create safer signatures.
tags: typescript, javascript, webdev
cover_image: https://javadesde0.com/wp-content/uploads/typescript-1280x720.jpg
---
Imagine you have a function like this one:

```ts
interface Post {
  id: number
  title: string
}

export function getPosts(page: number): Post[] {
  // perform some query to return posts from a database
  // ...
  // ...
  return []
}
```

`getPosts` accepts a `page` argument and retrieves posts from a data source.

Now, what if `getPosts` is used like this?

```ts
const posts = getPosts(-1);
```

Obviously That's incorrect because a page number can not be negative. A simple solution would be add a line like this one:

```ts
if(page < 0) throw Error('Page must be a positive number')`
```

But would not be nice if we receive a type error when we try to call the function with a negative number?

The problem here, is that the type `number` is too general for our function. `number` can be any number and we are expecting just a positive number.

We can create a type alias for it:

```ts
type PositiveNumber = number;
```

Although it makes our code more readable, using a simple alias doesn't solve the problem. Because we are still able to pass any number as an argument to `getPosts()`.

This is when we can create a **Branded Type.**

## Branded Types

When the base type is too general we can use this pattern.

```ts
type PositiveNumber = number & { __type: 'PositiveNumber' };
```

Here we are using an intersection between the base type (`number`) and an object with the `__type` property, this *private* property holds the brand type, and its used to differentiate it from a regular `number`.

We can rewrite our function to:

```ts
type PositiveNumber = number & { __type: 'PositiveNumber' };

export function getPosts(page: PositiveNumber): Post[] {
  // ...
  return []
}
```

Now if we try to call it like before, we're going to receive the error we expect.

```ts
const posts = getPosts(-1); 
// ^^^ Argument of type 'number' is not assignable to parameter of type 'PositiveNumber'.
```

Let's try with a valid number:

```ts
const posts = getPosts(2); 
// ^^^ Argument of type 'number' is not assignable to parameter of type 'PositiveNumber'.
```

Hmm, that's doesn't make sense 🤔, I'm sure `2` is a positive number.

We are still receiving the same error because we are still passing a `number`, not a `PositiveNumber`. Son wee need to explicitly say to the compiler that we are passing a `PositiveNumber` using the `as` keyword.

```ts
const posts = getPosts(2 as PositiveNumber); 
```

That will get rid of the error.

Now, what if we have a variable that we can't tell if it's a positive number or not?


```ts
const { page } = incomingRequest.body;  
// here, page could be a positive or a negative number, so we can't use the `as` keyword because we can't be sure of what is the actual value;

const posts = getPosts(page); 
```

To solve this we can use an **assertion function** that asserts page is an actual `PositiveNumber`

```ts
function assertsPositiveNumber(value: number): asserts value is PositiveNumber {
  if(value < 0) throw new Error('Value must be a positive number');
}
```

Now with this assertion, we can tell if `page` is a positive number or not.

```ts
const { page } = incomingRequest.body;  

assertsPositiveNumber(page);

const posts = getPosts(page); // at this point TypeScript know that `page` its a PositiveNumber
```

---

**If you liked this tip, please, share it and hit the ♥**

## Further Reading:

- [Assertion Functions](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html#assertion-functions)

- [Branding and Type-Tagging](https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d)