DEV Community

Strange
Strange

Posted on

Leveraging Conditional Properties Type Checking with Discriminated Unions

Strict type checking feels like a privilege ever since I encountered it in my career and i'll give anything to have it in any part of my code. So i decided to write this short post (for strict type checking fandom๐Ÿ˜Œ) to share a trick for type checking conditional properties of an entity .

I am just going to go straight to stating the problem so you can better understand what we are dealing with, (actually Its because I fear boring you more than anything). And also to stick with the goal; keep the post short.

Problem statement

The first thing I'll like to note is, this example is super contrived and there are better ways to go about this in a real world scenario. It however complements what we are trying to achieve so, here we go.

Create user props type

In our application, we have a createUser function that takes the properties of a user as described in the CreateUserAttr type. We have two types of users (Admin & User). The two variations of CreateUserAttr have some shared props and differences which are marked as optional props of the CreateUserAttr because we want to pass admin only props when creating an admin and vice versa. Hence the problem; the role prop when creating a user type of Admin is not optional (as seen below), we have to provide role and all other props related to the Admin type (super contrived ๐Ÿ˜‰) likewise the verified prop when creating a user type of User.

function call without strict type checking

Solution ๐Ÿ˜‹

The solution is to take advantage of typescript's union and intersection types to create a type known as discriminated union or tagged unions. We first create our base type which has all the shared props between the User & Admin type. Then we intersect it with a block that has two union type where we'll add the admin props and the user props. Putting everything together we have a type that has our shared props AND either the Admin props OR the User props.

discriminated union or tagged union in typescript

Now we get the yelling when we don't pass the all the required props relating to the type of User we are creating, SWEET!

Create admin with missing prop

Hooray๐ŸŽ‰! we now have type checking to make sure we are passing the required props of the user type being created, and also check that we don't pass a prop that doesn't belong. The example we have explored is intentionally simple to illustrate the core concept, but in real-world applications, the benefits become even more apparent. You can explore more examples here.

function call with type checking on discriminated union

Conclusion

In the world of software development, the privilege of strict type checking is indeed a treasure for those who have experienced its benefits. The added advantage of this approach is, our code becomes more readable (it's clear which property belongs to which union) and autocompletion (depending on the IDE). Our Types also become easy to extend because adding new types to the union is straightforward. So, whether you're tackling simple examples or navigating the complexities of real-world applications, discriminated unions offer a potent tool to make your code more robust, reliable, and enjoyable to work with.

And don't hesitate to drop a comment if you have any specific topics you'd like me to cover in future contentโค๏ธ.

Top comments (1)

Collapse
 
adamutako profile image
Adamu Tako

Good read, keep up the good work.