diff --git a/source/tagged-union.d.ts b/source/tagged-union.d.ts index 2419ca1c7..6f848d591 100644 --- a/source/tagged-union.d.ts +++ b/source/tagged-union.d.ts @@ -7,7 +7,7 @@ Use-case: A shorter way to declare tagged unions with multiple members. ``` import type {TaggedUnion} from 'type-fest'; -type Tagged>> = TaggedUnion<'type', Fields>; +type Tagged> = 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<{ @@ -45,7 +45,7 @@ type ManualEventMessage = */ export type TaggedUnion< TagKey extends string, - UnionMembers extends Record>, + UnionMembers extends Record, > = { [Name in keyof UnionMembers]: {[Key in TagKey]: Name} & UnionMembers[Name]; }[keyof UnionMembers]; diff --git a/test-d/tagged-union.ts b/test-d/tagged-union.ts index 570143d11..bd0c4e963 100644 --- a/test-d/tagged-union.ts +++ b/test-d/tagged-union.ts @@ -28,3 +28,18 @@ const failsToo = { expectNotAssignable(fails); expectNotAssignable(failsToo); + +// Issue #1211: `TaggedUnion` should be usable through a generic wrapper whose +// members are constrained as `Record`, as shown in the docs. +type Tagged> = TaggedUnion<'type', Fields>; + +type EventMessage = Tagged<{ + OpenExternalUrl: {url: string; id: number}; + ToggleBackButtonVisibility: {visible: boolean}; +}>; + +expectAssignable({type: 'OpenExternalUrl', url: 'https://example.com', id: 1}); +expectAssignable({type: 'ToggleBackButtonVisibility', visible: true}); + +// The discriminant still narrows the field types correctly. +expectNotAssignable({type: 'ToggleBackButtonVisibility', visible: 'yes'});