Consider an enum:
enum TaskType {
WithId = 'WithId',
WithValues="WithValues",
WithNothing = 'WithNothing',
}
and corresponding classes which use the enum as a discriminator, but does not correctly assign the TaskWithId
value:
class TaskWithId {
type: TaskType; // note type is assigned the enum type and not a specific value
id: number;
}
class TaskWithValues {
type: TaskType.WithValues; // use specific enum value
values: number[];
}
class TaskWithNothing {
type: TaskType.WithNothing; // use specific enum value
}
export type Task = TaskWithId | TaskWithValues | TaskWithNothing;
If I use a switch
to narrow the type, it infers the TaskWithId
type correctly, despite specifying the discriminator enum incorrectly:
switch (task.type) {
case TaskType.WithId:
const id = task.id; // task type is inferred as TaskWithId despite non specific discriminator
break;
}
How is this ‘working’?
Furthemore, if I try and narrow TaskWithValues
, it does not work despite using a specific discriminator:
case TaskType.WithValues:
// const values = task.values; // task type includes TaskWithId, despite specific discriminator
Stackblitz: https://stackblitz.com/edit/typescript-fkha8n?file=index.ts
Your code doesn’t compile for me on TS Playground.
It’s working logically. There’s an ice cream shop that sells chocolate, vanilla, or strawberry ice cream. Three children: Charlie, Vanessa, and Quentin, order ice cream. Charlie orders chocolate and Vanessa orders vanilla. But you didn’t hear what Quentin ordered. The proprietor brings out one of the orders: it’s strawberry. Whose ice cream is it? It could only be Quentin’s. What if instead the proprietor brings out chocolate? Then it’s either Quentin’s or Charlie’s. That’s exactly what’s happening with your code. I’m wondering how else you could imagine it going.
(see prev comment). Quentin is TaskWithId, if it matters, and strawberry is
TaskType.WithId
. Does that fully address your confusion or is something still missing?Thanks, yeah I see now – it’s inferring the
TaskWithId
type because it’s the only type left in the union – it can’t be the other two as the discriminator doesn’t match.Right! So, uh, I guess I’ll write that up as an answer when I get a chance? Maybe without the ice cream 🍦🍨
Show 1 more comment