I’m struggling with handling different API response shapes. If I have a success object with data and an error object with a message, what is the best way to use Discriminated Unions to ensure type safety? I want to avoid using 'any' or manual type assertions when accessing specific properties.
3 answers
Using a common literal property, like 'status', is the gold standard here. You define a Type for Success and a Type for Failure, both sharing that 'status' key but with different string literals. When you wrap these in a Union, TypeScript’s control flow analysis kicks in. Inside an if-statement checking that status, the compiler automatically narrows the type, granting you safe access to the 'data' or 'message' property. It eliminates runtime errors and makes your code much more predictable for the rest of the team.
Does this approach also work effectively when dealing with deeply nested objects, or does the type narrowing become too verbose for the compiler to handle efficiently?
I always recommend using a 'kind' or 'type' field. It’s a pattern that significantly improves the developer experience in VS Code via better Intellisense.
Exactly, Michael. Using 'kind' as a discriminant is a standard practice in many large-scale TypeScript libraries to keep the logic clean and safe.
It scales perfectly, David! As long as the "discriminant" property is at the top level of the union members, TypeScript tracks it regardless of nesting depth. You can even use switch statements for better readability when you have more than two states, like 'loading', 'success', and 'unauthorized'.