Your eyes aren't fooling you... I finally did it. Real discriminated unions in Typescript, with a couple of extra OO superpowers, and compile time error validation.
const UploadState = union({
Initial: null,
Pending: {
Preparing: (fileName: string) => ({ fileName }),
Uploading: (progress: number) => ({ progress }),
Processing: (stage: string) => ({ stage })
},
Complete: (url: string) => ({ url }),
Failed: (reason: string) => ({ reason })
});
// Usage
const upload = UploadState.Pending.Uploading(45);
// Many ways to destruct a union
const getUploadStatus = match(upload).to({
Initial: () => "Ready to upload",
Pending: (state) => state.match({
Preparing: ({ fileName }) => `Preparing ${fileName}...`,
Uploading: ({ progress }) => `Uploading: ${progress}%`,
Processing: ({ stage }) => `Processing: ${stage}`
}),
Complete: ({ url }) => `Upload complete: ${url}`,
Failed: ({ reason }) => `Upload failed: ${reason}`
});
//...or
const getUploadStatus = match(upload).to({
Initial: () => "Ready to upload",
None: () => "I don't believe in 'Users'. What are those?"
});
//...or
const getUploadStatus = match.to<typeof UploadState>({
//the type system complains when you don't exhaust all options
Complete: ({ url }) => `Upload complete: ${url}`,
Failed: ({ reason }) => `Upload failed: ${reason}`,
None: () => `I got your load!` //use None as a catch all
})
🎶 Do you believe in magic?
I know there are other libraries on the market. But none quite like this (although, technically, this is not a "library" just yet. But once I'm done this journey, I will publish and package this for everyone's consumption).
Stay tuned.
Top comments (1)
you are on a roll! looking forward to switching my entire Rust stack to your upcoming TS library