DEV Community

Cover image for Return Type That Is Dependent On Argument's Type
Daniel Bellmas
Daniel Bellmas

Posted on • Edited on

Return Type That Is Dependent On Argument's Type

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

useBreakpoint hook

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

At the return we let Typescript know the hook's return type by using type assertions.


Types

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 value mapped to each breakpoint, for example:
const breakpointMap = { sm: "a", md: "b", lg: "c" }
Enter fullscreen mode Exit fullscreen mode

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 won't be with a union separator (undefined | T), 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, 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

  • When the breakpointMap is passed the type will be, in this instance, string:

breakpointMap passed

⛔️ Not Using

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

Not using this method

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

⚡️ Even though we passed the breakpointMap! ⚡️

T | undefined error


Press on Open Sandbox to play with the code 🎈


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

Typescript process meme

Top comments (0)