Improved Type Safety with Discriminated Tuples in TypeScript
The solution is to update Result
to be a discriminated tuple.
Basically, we'll take all of Result
's content and put it inside of 3 different tuples.
Here's what Result
looked like before:
// starting point
export type Result<T> = [
"loading" | "success" | "error",
T | Error | unde
Transcript
00:00 So, you might have figured out the solution here. It's really, really neat, which is we can use a discriminated tuple for this. So, let's say we take all of this and we basically put it inside three different tuples. So, tuple 1, tuple 2 and tuple 3. For the first
00:18 tuple, we're going to give the first member loading and the second member is going to be undefined here. For the second tuple, we can have success and this is going to be with our T attached to it. And you can see, as I filled in that, then this one worked here.
00:35 The other one that's not working is error any. So, let's put error and instead of any, let's use an error instead. So, now we've got our results properly typed. We've got loading undefined, success T, error, error. And now suddenly everything's working. Why
00:51 is it working? So, there's a few things to break down here. First of all, it's really smart that TypeScript understands that when you create this tuple, you get three different parts here, error, loading and success. I can't pass in an error, obviously, into success
01:05 because this is, like, it's not assignable to T. So, I have to start off with loading undefined. And by the way, you can also specify this as a kind of like an optional member of this tuple. So, I don't even need to pass this here if I don't want to, which is pretty
01:23 beautiful, actually. Then down here, we basically, this is really, really smart. When you destructure this, TypeScript understands the relationship between these two components. It understands
01:37 that if status is a certain thing, then value is going to be a certain thing, too. So, this breaks the rule or breaks our understanding of destructuring because you think of, like, destructuring a discriminated union of objects, this wouldn't work, surely. But with tuples,
01:53 it does. This is so, so smart. And it means, actually, we just get a really clean API up here and a really clean API down here. So, I would recommend actually using this more often, and I'm surprised that more libraries don't. It's just a really, really lovely way
02:09 to kind of make your code more understandable for the people that are consuming the functions of your library. Lovely stuff.