Skip to content
Open
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions source/tagged-union.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Use-case: A shorter way to declare tagged unions with multiple members.
```
import type {TaggedUnion} from 'type-fest';

type Tagged<Fields extends Record<string, Record<string, unknown>>> = TaggedUnion<'type', Fields>;
type Tagged<Fields extends Record<string, unknown>> = TaggedUnion<'type', Fields>;

// The TaggedUnion utility reduces the amount of boilerplate needed to create a tagged union with multiple members, making the code more concise.
type EventMessage = Tagged<{
Expand Down Expand Up @@ -45,7 +45,7 @@ type ManualEventMessage =
*/
export type TaggedUnion<
TagKey extends string,
UnionMembers extends Record<string, Record<string, unknown>>,
UnionMembers extends Record<string, unknown>,
> = {
[Name in keyof UnionMembers]: {[Key in TagKey]: Name} & UnionMembers[Name];
}[keyof UnionMembers];
Expand Down
15 changes: 15 additions & 0 deletions test-d/tagged-union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,18 @@ const failsToo = {

expectNotAssignable<Union>(fails);
expectNotAssignable<Union>(failsToo);

// Issue #1211: `TaggedUnion` should be usable through a generic wrapper whose
// members are constrained as `Record<string, unknown>`, as shown in the docs.
type Tagged<Fields extends Record<string, unknown>> = TaggedUnion<'type', Fields>;

type EventMessage = Tagged<{
OpenExternalUrl: {url: string; id: number};
ToggleBackButtonVisibility: {visible: boolean};
}>;

expectAssignable<EventMessage>({type: 'OpenExternalUrl', url: 'https://example.com', id: 1});
expectAssignable<EventMessage>({type: 'ToggleBackButtonVisibility', visible: true});

// The discriminant still narrows the field types correctly.
expectNotAssignable<EventMessage>({type: 'ToggleBackButtonVisibility', visible: 'yes'});