Return Type That Is Dependent On Argument's Type
Tags: typescript, react, hooks, webdev
Published: 2022-10-10 13:56:25

In this example, the return type of a hook depends on whether the argument is passed.


![useBreakpoint hook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ig1oxgol6u7t6atni720.png)


So here we have a `useBreakpoint` hook that, from the screen resolution, gives us the current breakpoint we're on; and it also allows us to **optionally** pass a `breakpointMap`, which is just an object that maps a breakpoint to some styles we want to change according to the current breakpoint (`activeBreakpoint`).


### The Objective
Tell Typescript to make `mappedValue`'s type `undefined` only if the `breakpointMap`(the argument) **is not passed**.
If it **is passed**, we want it to be defined as the value of the mapped object.


---

![The return type](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sud1qi1lgx9pz25dwe7l.png)

At the return we let Typescript know the hook's return type by using [type assertions](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions).

---------

![Types](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rwcl7h52lah21sgypyvj.png)

We can use the power of Generics as if they were function arguments.

`UseBreakpointsResult` receives 2 generic types `T` and `V`.
- **`T`** is the type of the <u>value mapped to each breakpoint</u>, for example:
```ts
const breakpointMap = { sm: "a", md: "b", lg: "c" }
```
Here, `T` will be a `string`, because `"a"` or `"b"` or `"c"` are the values there are mapped.

- **`V`** - we pass `typeof breakpointMap`, which can either be `undefined` (no arguments passed) or `T` (a map object was passed).

#### The important thing to understand here is that `mappedValue`'s type <u>won't be with a union separator (`undefined | T`)</u>, it's **either** `T` **or** `undefined`.
That is done by asking: `V extends undefined ? never : T`
> If `V` is `undefined` then we don't want the `mappedValue`, otherwise let `mappedValue`'s type be `T`.


### Why is it so critical to tell `Typescript` `mappedValue` should either be `undefined` or `T`?

If we don't check the type of the argument then the type is either `T | undefined`, which means we have to check if it's `undefined` every time before we render our component, or add a [Non-null assertion operator](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator), which  will uglify the code unnecessarily.


## Using vs. Not Using This Method 

### ✅ Using

- When the `breakpointMap` **is not passed** the type will be `undefined`:

![breakpointMap not passed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xhcoibtv2vdsdcfvg49f.png)

- When the `breakpointMap` **is passed** the type will be, in this instance, `string`:


![breakpointMap passed](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yeofp058rqlqzpou7u5q.png)

### ⛔️ Not Using

Here we define the `mappedValue`'s type to be `T | undefined`.

![Not using this method](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1ehp10p940h51lx0x2g.png)


- When `mappedValue`'s type is `T | undefined` we'll get this error:

#### ⚡️ Even though we passed the `breakpointMap`! ⚡️

![T | undefined error](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb2wxwvpx53vcp3nduaq.png)

---
#### Press on `Open Sandbox` to play with the code 🎈

{% embed https://codesandbox.io/embed/return-type-of-hook-dependent-on-arguments-type-djiebi?fontsize=14&hidenavigation=1&theme=dark %}

---

Typescript helps us to better communicate our intentions and understand others' intentions.
So be like this bird and go explore Typescript! 🗺 🦅

![Typescript process meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5i2g5yt5gkvv5tb1thug.png)