mirror of
https://github.com/sindresorhus/type-fest.git
synced 2025-12-08 19:25:05 +00:00
Add TaggedUnion type (#566)
This commit is contained in:
parent
9b12767a2f
commit
2e1cec8aaf
1
index.d.ts
vendored
1
index.d.ts
vendored
@ -7,6 +7,7 @@ export * from './source/observable-like';
|
||||
// Utilities
|
||||
export type {EmptyObject, IsEmptyObject} from './source/empty-object';
|
||||
export type {Except} from './source/except';
|
||||
export type {TaggedUnion} from './source/tagged-union';
|
||||
export type {Writable} from './source/writable';
|
||||
export type {WritableDeep} from './source/writable-deep';
|
||||
export type {Merge} from './source/merge';
|
||||
|
||||
@ -178,6 +178,7 @@ Click the type names for complete docs.
|
||||
- [`IsNumericLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `number` or `bigint` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
||||
- [`IsBooleanLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `true` or `false` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
||||
- [`IsSymbolLiteral`](source/is-literal.d.ts) - Returns a boolean for whether the given type is a `symbol` [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types).
|
||||
- [`TaggedUnion`](source/tagged-union.d.ts) - Create a union of types that share a common discriminant property.
|
||||
|
||||
### JSON
|
||||
|
||||
|
||||
51
source/tagged-union.d.ts
vendored
Normal file
51
source/tagged-union.d.ts
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/**
|
||||
Create a union of types that share a common discriminant property.
|
||||
|
||||
Use-case: A shorter way to declare tagged unions with multiple members.
|
||||
|
||||
@example
|
||||
```
|
||||
import type {TaggedUnion} from 'type-fest';
|
||||
|
||||
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<{
|
||||
OpenExternalUrl: {
|
||||
url: string;
|
||||
id: number;
|
||||
language: string;
|
||||
};
|
||||
ToggleBackButtonVisibility: {
|
||||
visible: boolean;
|
||||
};
|
||||
PurchaseButtonPressed: {
|
||||
price: number;
|
||||
time: Date;
|
||||
};
|
||||
NavigationStateChanged: {
|
||||
navigation?: string;
|
||||
};
|
||||
}>;
|
||||
|
||||
// Here is the same type created without this utility.
|
||||
type EventMessage =
|
||||
| {
|
||||
type: 'OpenExternalUrl';
|
||||
url: string;
|
||||
id: number;
|
||||
language: string;
|
||||
}
|
||||
| {type: 'ToggleBackButtonVisibility'; visible: boolean}
|
||||
| {type: 'PurchaseButtonPressed'; price: number; time: Date}
|
||||
| {type: 'NavigationStateChanged'; navigation?: string};
|
||||
```
|
||||
|
||||
@category Utilities
|
||||
*/
|
||||
export type TaggedUnion<
|
||||
TagKey extends string,
|
||||
UnionMembers extends Record<string, Record<string, unknown>>,
|
||||
> = {
|
||||
[Name in keyof UnionMembers]: {[Key in TagKey]: Name} & UnionMembers[Name];
|
||||
}[keyof UnionMembers];
|
||||
30
test-d/tagged-union.ts
Normal file
30
test-d/tagged-union.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import {expectAssignable, expectNotAssignable} from 'tsd';
|
||||
import type {TaggedUnion} from '../index';
|
||||
|
||||
type Union = TaggedUnion<'tag', {str: {a: string} ; num: {b: number}}>;
|
||||
|
||||
const first = {
|
||||
tag: 'str' as const,
|
||||
a: 'some-string',
|
||||
};
|
||||
|
||||
const second = {
|
||||
tag: 'num' as const,
|
||||
b: 1,
|
||||
};
|
||||
|
||||
expectAssignable<Union>(first);
|
||||
expectAssignable<Union>(second);
|
||||
|
||||
const fails = {
|
||||
tag: 'num' as const,
|
||||
b: 'should not be string',
|
||||
};
|
||||
|
||||
const failsToo = {
|
||||
tag: 'str' as const,
|
||||
b: 2,
|
||||
};
|
||||
|
||||
expectNotAssignable<Union>(fails);
|
||||
expectNotAssignable<Union>(failsToo);
|
||||
Loading…
x
Reference in New Issue
Block a user