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.
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
.
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.
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!
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.
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)
Good read, keep up the good work.