Skip to content

Correct the section about discriminated union types #183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions ADVANCED.md
Original file line number Diff line number Diff line change
Expand Up @@ -501,23 +501,6 @@ You may also want to use Discriminated Unions, please check out [Expressive Reac

Here is a brief intuition for **Discriminated Union Types**:

```ts
type UserTextEvent = { value: string; target: HTMLInputElement };
type UserMouseEvent = { value: [number, number]; target: HTMLElement };
type UserEvent = UserTextEvent | UserMouseEvent;
function handle(event: UserEvent) {
if (typeof event.value === "string") {
event.value; // string
event.target; // HTMLInputElement | HTMLElement (!!!!)
return;
}
event.value; // [number, number]
event.target; // HTMLInputElement | HTMLElement (!!!!)
}
```

Even though we have narrowed based on `event.value`, the logic doesn't filter up and sideways to `event.target`. This is because a union type `UserTextEvent | UserMouseEvent` could be BOTH at once. So TypeScript needs a better hint. The solution is to use a literal type to tag each case of your union type:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the example should not be deleted. It's a good illustration. But you are correct, the language here does sound confusing.

You can move it below the actual example and collapse it.
You can change the explanation to "
Take care: TypeScript does not narrow the type of a Discriminated Union on the basis of typeof checks. The type guard has to be on the value of a key and not it's type.
microsoft/TypeScript#30506 (comment)
"


```ts
type UserTextEvent = {
type: "TextEvent";
Expand All @@ -544,8 +527,8 @@ function handle(event: UserEvent) {
To streamline this you may also combine this with the concept of **User-Defined Type Guards**:

```ts
function isString(a: unknown): a is string {
return typeof a === "string";
function isMouseEvent(a: unknown): a is MouseEvent {
return a && a.type === "MouseEvent";
}
```

Expand Down