and Flow are pretty cool for a bunch of reasons. I wanted to highlight one such case while using them with . Specifically, we will see how tagged unions can give us better documentation and assurances with redux connected components. This article will assume some basic understanding of types. Typescript React The need Let’s start by building something, a simple chat app. It will fetch the logged in user, the list of users chatting, and render it all to the screen. Nothing terribly exciting, but the app has some interesting states it can be in. For example it can be: offline where we won’t see other users, loading where we will see some loading indicator, and a loaded state where we will see ourself along with the other users. Connecting our component To get the ball rolling, here is a quick and dirty solution to hooking up our component to our redux store. We won’t bother writing the view or the connect function yet, we will focus on the return value of the function which gets passed down as props to our view. mapStateToProps type MapStateToPropsResult= { loading?: boolean, disconnected?: boolean, users?: User[], activeUser?: User} Simple enough: an object with all optional properties. This is totally usable; we could continue on our merry way and the type system would happily make us check if each property exists before we use them. Do you see any problems though? The business requirements have clear relationships between these properties, but none of it can be inferred by looking at this code. It doesn’t make sense that we would have or while the screen is loading. Also, it wouldn't make sense if we could talk with users while the app knows it is offline. All of these subtleties are lost if we simply make everything optional. users activeUser Secondly, we missed a valuable opportunity to . It is all too easy to simply go about types passively, write code and the compiler is just there as a safety net to make sure you don’t make any typos. If we actively think about how types work in our system, we can have the compiler guide us to correct solutions. use the type system as a tool With this in mind, let’s revise our type signature. type MapStateToPropsResult= { uiState: 'loading' }| { uiState: 'disconnected', activeUser: User }| { uiState: 'loaded', activeUser: User, users: User[] } We have taken our single object of all optional properties and split it into a union of three objects with all required properties. Now, when you look at this type, you can quickly see the relationship between properties and what state the UI is in. It is now clear that when the app is loading we won’t have access to or . Similarly, we wont have access to when we are disconnected. user activeUser users Lastly, we can leverage this type to make the compiler guide us to writing code that adheres to our business logic! @connect((state, props): MapStateToPropsResult => { })class UserList extends React.Component// ... We have stubbed out our class and function and told the compiler that this function will return the type we just defined. Right away the compiler sees that we are not returning a value of the union type and it will start to guide us to correct code. mapStateToProps @connect((state, props): MapStateToPropsResult => {const activeUser = selectActiveUser(state) // User | undefinedconst users = selectOtherUsers(state) // User[] | undefined if (activeUser) { return { uiState: 'loaded', activeUser, users } // ERROR } })class UserList extends React.Component// ... Above for example, perhaps we have finished fetching the data, but we are still waiting on to come back from the server. Since both and are required in , this type will force us to render a state instead. activeUser users users activeUser loaded loading By making all the properties in the type required, we are telling the compiler to us to deal with loading states. force The view Now how is this beneficial from the view’s perspective? For starters, now we won’t be able to access properties within the union until we figure out what state we are in. class UserList extends React.Component {render() {const user = this.props.activeUser // Error!}} For example above, the type system doesn’t know if we are etc, therefore it can't be assured that exists on our . So what would a real example look like? loading activeUser props class UserList extends React.Component {renderLoading() { /* ... */ }renderDisconnected(activeUser) { /* ... */ }renderLoaded(activeUser, users) { /* ... */ } render() { const { uiState } = this.props if (uiState === 'loading') return this.renderLoading() const { activeUser } = this.props if (uiState === 'disconnected') return this.renderDisconnected(activeUser) const { users } = this.props if (uiState === 'loaded') return this.renderLoaded(activeUser, users) } } This is just one way we could approach the view logic. It is interesting to see how more props become available to us as we narrow down what the union can and can’t be. After the first conditional where we check if the type system can then infer that the remaining states both contain and therefore lets us access it via props. uiState === 'loading' activeUser Another interesting aspect is it can inform us if we are missing cases in our render function. Perhaps down the road we add another case to our union, and it is rendered with slight differences. The type system will then pick up on this change and let us know that our render function doesn't always return , (assuming we type the return value of the render function). away, JSX Last thoughts If you have stuck with me thus far, you may be able to tell that I am quite jazzed about this. Dynamic languages are wonderful for many, many reasons. However coming to the world of typed languages, there are entirely new realms of expressive power just waiting to be exploited. I know there is some adage “Work will always fill all available time.” Well, in my case it is “If there is a lazier way to do it, I still wouldn’t do it because it probably would take too much effort.” Any opportunity I can get to have some one else force me to do my job properly is a huge win. In this case, I can (intentionally) have a cold, heartless, omnipotent computer force me to actually do my job properly. With all this said and done, here are a few bullet points for posterity sake: Union types are helpful outside of raw data. Use them for return values coming out of connect or props into your components. Really, they are really, really awesome. If you see multiple optionals start creeping into your types, consider breaking it into a union where things are not optional. Think through your types first. If you tell the compiler the shape of the function and it’s results up front, it will help you write correct code. I have really enjoyed reading , , and . They all deal with structuring types to make states that shouldn’t happen, not happen. They are all super illuminating and are all applicable across languages. this piece by Yaron Minsky this one by Scott Wlaschin this one by Richard Feldman Lastly, types give us a unique opportunity to embed and enforce business logic at compile time. It truly is worth it to add a few characters for the safety and documentation they will provide down the road. is how hackers start their afternoons. We’re a part of the family. We are now and happy to opportunities. Hacker Noon @AMI accepting submissions discuss advertising &sponsorship To learn more, , , or simply, read our about page like/message us on Facebook tweet/DM @HackerNoon. If you enjoyed this story, we recommend reading our and . Until next time, don’t take the realities of the world for granted! latest tech stories trending tech stories