Skip to content

Commit 2fabfe0

Browse files
committed
docs(advanced) Correct the section about discrinated types (#205)
1 parent e89d615 commit 2fabfe0

File tree

1 file changed

+24
-17
lines changed

1 file changed

+24
-17
lines changed

ADVANCED.md

+24-17
Original file line numberDiff line numberDiff line change
@@ -511,23 +511,6 @@ You may also want to use Discriminated Unions, please check out [Expressive Reac
511511

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

514-
```ts
515-
type UserTextEvent = { value: string; target: HTMLInputElement };
516-
type UserMouseEvent = { value: [number, number]; target: HTMLElement };
517-
type UserEvent = UserTextEvent | UserMouseEvent;
518-
function handle(event: UserEvent) {
519-
if (typeof event.value === "string") {
520-
event.value; // string
521-
event.target; // HTMLInputElement | HTMLElement (!!!!)
522-
return;
523-
}
524-
event.value; // [number, number]
525-
event.target; // HTMLInputElement | HTMLElement (!!!!)
526-
}
527-
```
528-
529-
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:
530-
531514
```ts
532515
type UserTextEvent = {
533516
type: "TextEvent";
@@ -551,6 +534,30 @@ function handle(event: UserEvent) {
551534
}
552535
```
553536

537+
<details>
538+
<summary>
539+
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.
540+
</summary>
541+
542+
```ts
543+
type UserTextEvent = { value: string; target: HTMLInputElement };
544+
type UserMouseEvent = { value: [number, number]; target: HTMLElement };
545+
type UserEvent = UserTextEvent | UserMouseEvent;
546+
function handle(event: UserEvent) {
547+
if (typeof event.value === "string") {
548+
event.value; // string
549+
event.target; // HTMLInputElement | HTMLElement (!!!!)
550+
return;
551+
}
552+
event.value; // [number, number]
553+
event.target; // HTMLInputElement | HTMLElement (!!!!)
554+
}
555+
```
556+
557+
The above example does not work as we are not checking the value of `event.value` but only it's type. Read more about it [microsoft/TypeScript#30506 (comment)](https://github.com/microsoft/TypeScript/issues/30506#issuecomment-474858198)
558+
559+
</details>
560+
554561
To streamline this you may also combine this with the concept of **User-Defined Type Guards**:
555562

556563
```ts

0 commit comments

Comments
 (0)