𝗧𝘆𝗽𝗲𝗦𝗰𝗿𝗶𝗽𝘁 𝗗𝗶𝘀𝗰𝗿𝗶𝗺𝗶𝗻𝗮𝘁𝗲𝗱 𝗨𝗻𝗶𝗼𝗻𝘀
You have a type with data, an error, and an isLoading field.
You know only one of these should exist at a time. TypeScript does not.
Every time you access these fields, you risk a runtime crash. You spend your time writing endless null checks. This code is fragile.
The fix is a discriminated union. It is a top tier pattern in TypeScript.
Stop using this pattern:
- data: User[] | null
- error: string | null
- isLoading: boolean
This allows impossible states. You could have data, an error, and a loading flag all set to true. Your code has to guess what is happening.
Use this pattern instead:
- status: "loading"
- status: "success" with data
- status: "error" with error message
Now, impossible states cannot exist. You cannot have data and an error at the same time.
TypeScript makes narrowing easy. When you use a switch statement on the status field, the compiler knows exactly which data is available.
If you are in the "success" branch, you have access to data. If you are in the "error" branch, you have access to the error message. If you try to access data in the error branch, TypeScript stops you.
This safety happens at compile time. You do not rely on discipline or runtime checks.
You can apply this to many areas:
API States Model your requests as idle, loading, success, or error. This prevents accidental access to old data while a new request loads.
Form States Forms have lifecycles. Use states like editing, submitting, validation_error, or success. A "submitting" state should not carry "dirty" or "error" data.
Modal States Avoid using multiple boolean flags for modals. Use a single type to define if a modal is closed, confirming a delete, or editing an item.
Pro tip: Use the "never" type to ensure exhaustiveness.
If you add a new state to your union, TypeScript will throw an error if you forget to handle it in your switch statement. This forces you to write complete code.
Discriminated unions turn runtime errors into compile errors. They make your code predictable.
Stop writing types that describe bugs. Make impossible states impossible.
Source: https://dev.to/kaithorne/typescript-discriminated-unions-making-impossible-states-impossible-8me