0
# Union Module
1
2
Union type operations including set operations, filtering, transformations, and nullability handling for working with union types effectively.
3
4
## Capabilities
5
6
### Set Operations
7
8
Core set operations treating unions as mathematical sets.
9
10
```typescript { .api }
11
/**
12
* Exclude types from union (set difference)
13
* @param U - Union to exclude from
14
* @param E - Types to exclude
15
* @returns Union without excluded types
16
*/
17
type Exclude<U, E> = U extends E ? never : U;
18
19
/**
20
* Extract types from union (set intersection)
21
* @param U - Union to extract from
22
* @param E - Types to extract
23
* @returns Only extracted types from union
24
*/
25
type Extract<U, E> = U extends E ? U : never;
26
27
/**
28
* Set intersection of two unions
29
* @param U1 - First union
30
* @param U2 - Second union
31
* @returns Types common to both unions
32
*/
33
type Intersect<U1, U2> = Extract<U1, U2>;
34
35
/**
36
* Set difference of two unions
37
* @param U1 - First union
38
* @param U2 - Second union
39
* @returns Types in U1 but not in U2
40
*/
41
type Diff<U1, U2> = Exclude<U1, U2>;
42
```
43
44
**Usage Examples:**
45
46
```typescript
47
import { U } from "ts-toolbelt";
48
49
type Numbers = 1 | 2 | 3 | 4 | 5;
50
type EvenNumbers = 2 | 4 | 6 | 8;
51
type Strings = "a" | "b" | "c";
52
53
// Exclude operations
54
type OddNumbers = U.Exclude<Numbers, EvenNumbers>; // 1 | 3 | 5
55
type NonStrings = U.Exclude<string | number | boolean, string>; // number | boolean
56
57
// Extract operations
58
type CommonNumbers = U.Extract<Numbers, EvenNumbers>; // 2 | 4
59
type OnlyStrings = U.Extract<string | number | boolean, string>; // string
60
61
// Set operations
62
type Intersection = U.Intersect<Numbers, EvenNumbers>; // 2 | 4
63
type Difference = U.Diff<Numbers, EvenNumbers>; // 1 | 3 | 5
64
65
// Complex set operations
66
type Mixed1 = string | number | boolean;
67
type Mixed2 = string | object | null;
68
type CommonTypes = U.Intersect<Mixed1, Mixed2>; // string
69
type UniqueToFirst = U.Diff<Mixed1, Mixed2>; // number | boolean
70
```
71
72
### Union Queries
73
74
Query operations to check membership and properties of unions.
75
76
```typescript { .api }
77
/**
78
* Check if union contains a specific type
79
* @param U - Union to check
80
* @param A - Type to look for
81
* @returns 1 if type is in union, 0 otherwise
82
*/
83
type Has<U, A> = A extends U ? 1 : 0;
84
85
/**
86
* Get last member of union (implementation-dependent)
87
* @param U - Union to get last member from
88
* @returns Last union member
89
*/
90
type Last<U> = LastImpl<U>;
91
```
92
93
**Usage Examples:**
94
95
```typescript
96
import { U } from "ts-toolbelt";
97
98
type Primitives = string | number | boolean;
99
100
// Check membership
101
type HasString = U.Has<Primitives, string>; // 1
102
type HasObject = U.Has<Primitives, object>; // 0
103
type HasBoolean = U.Has<Primitives, boolean>; // 1
104
105
// Get last member
106
type LastPrimitive = U.Last<Primitives>; // boolean (implementation-dependent)
107
108
// Conditional logic based on membership
109
type ConditionalType<T> = U.Has<string | number, T> extends 1
110
? "primitive"
111
: "other";
112
113
type Test1 = ConditionalType<string>; // "primitive"
114
type Test2 = ConditionalType<object>; // "other"
115
```
116
117
### Union Transformations
118
119
Transform unions into other forms and manipulate their structure.
120
121
```typescript { .api }
122
/**
123
* Make union not allow excess properties (strict object unions)
124
* @param U - Union of objects to make strict
125
* @returns Union with strict property checking
126
*/
127
type Strict<U extends object> = ComputeRaw<_Strict<U>>;
128
129
/**
130
* Merge union of object types into single intersection
131
* @param U - Union of objects to merge
132
* @returns Intersection of all object types
133
*/
134
type Merge<U> = MergeImpl<U>;
135
136
/**
137
* Transform union to intersection type
138
* @param U - Union to transform to intersection
139
* @returns Intersection of all union members
140
*/
141
type IntersectOf<U extends any> = (U extends unknown ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
142
143
/**
144
* Convert union to list/tuple
145
* @param U - Union to convert
146
* @returns Tuple containing union members
147
*/
148
type ListOf<U> = ListOfImpl<U>;
149
150
/**
151
* Remove last member from union
152
* @param U - Union to pop from
153
* @returns Union without last member
154
*/
155
type Pop<U> = PopImpl<U>;
156
157
/**
158
* Replace types in union
159
* @param U - Union to replace in
160
* @param From - Type to replace
161
* @param To - Replacement type
162
* @returns Union with replaced types
163
*/
164
type Replace<U, From, To> = U extends From ? To : U;
165
```
166
167
**Usage Examples:**
168
169
```typescript
170
import { U } from "ts-toolbelt";
171
172
// Union merging
173
type User = { name: string };
174
type Profile = { age: number };
175
type Settings = { theme: string };
176
type UserUnion = User | Profile | Settings;
177
178
type MergedUser = U.Merge<UserUnion>; // { name: string } & { age: number } & { theme: string }
179
180
// Union to intersection - useful for function overloads
181
type Func1 = (a: string) => void;
182
type Func2 = (a: number) => void;
183
type UnionFunc = Func1 | Func2;
184
type IntersectedFunc = U.IntersectOf<UnionFunc>; // (a: string) => void & (a: number) => void
185
186
// Strict unions prevent excess properties
187
type Cat = { type: "cat"; meow: boolean };
188
type Dog = { type: "dog"; bark: boolean };
189
type Animal = Cat | Dog;
190
type StrictAnimal = U.Strict<Animal>; // Prevents { type: "cat"; meow: true; extraProp: any }
191
192
// Union to list
193
type PrimitiveUnion = string | number | boolean;
194
type PrimitiveList = U.ListOf<PrimitiveUnion>; // [string, number, boolean] (order may vary)
195
196
// Replace in union
197
type Original = "red" | "green" | "blue";
198
type Updated = U.Replace<Original, "red", "crimson">; // "crimson" | "green" | "blue"
199
200
// Pop from union
201
type Colors = "red" | "green" | "blue";
202
type FewerColors = U.Pop<Colors>; // "red" | "green" (removes last, implementation-dependent)
203
204
// Multiple replacements
205
type StatusCodes = 200 | 404 | 500;
206
type UpdatedCodes = U.Replace<U.Replace<StatusCodes, 404, 400>, 500, 503>; // 200 | 400 | 503
207
```
208
209
### Union Filtering
210
211
Filter union members based on conditions and criteria.
212
213
```typescript { .api }
214
/**
215
* Filter union members based on condition
216
* @param U - Union to filter
217
* @param M - Filter condition/matcher
218
* @returns Union members matching condition
219
*/
220
type Filter<U, M> = FilterImpl<U, M>;
221
222
/**
223
* Select union members based on condition
224
* @param U - Union to select from
225
* @param C - Selection condition
226
* @returns Selected union members
227
*/
228
type Select<U, C> = SelectImpl<U, C>;
229
```
230
231
**Usage Examples:**
232
233
```typescript
234
import { U } from "ts-toolbelt";
235
236
// Filter by type
237
type Mixed = string | number | boolean | null | undefined;
238
type OnlyPrimitives = U.Filter<Mixed, string | number | boolean>; // string | number | boolean
239
type NoNullish = U.Filter<Mixed, Exclude<Mixed, null | undefined>>; // string | number | boolean
240
241
// Select by condition (conceptual - actual implementation varies)
242
type SelectStrings = U.Select<Mixed, string>; // string
243
type SelectNumbers = U.Select<Mixed, number>; // number
244
245
// Complex filtering
246
type ObjectTypes = { a: string } | { b: number } | string | number;
247
type OnlyObjects = U.Filter<ObjectTypes, object>; // { a: string } | { b: number }
248
type OnlyPrimitiveTypes = U.Filter<ObjectTypes, string | number>; // string | number
249
```
250
251
### Nullability Operations
252
253
Handle null and undefined types within unions.
254
255
```typescript { .api }
256
/**
257
* Remove null and undefined from union
258
* @param U - Union to make non-nullable
259
* @returns Union without null or undefined
260
*/
261
type NonNullable<U> = U extends null | undefined ? never : U;
262
263
/**
264
* Add null to union
265
* @param U - Union to make nullable
266
* @returns Union with null added
267
*/
268
type Nullable<U> = U | null;
269
```
270
271
**Usage Examples:**
272
273
```typescript
274
import { U } from "ts-toolbelt";
275
276
// Non-nullable operations
277
type MaybeString = string | null | undefined;
278
type DefinitelyString = U.NonNullable<MaybeString>; // string
279
280
type Optional = number | boolean | null | undefined;
281
type Required = U.NonNullable<Optional>; // number | boolean
282
283
// Make nullable
284
type Primitives = string | number | boolean;
285
type NullablePrimitives = U.Nullable<Primitives>; // string | number | boolean | null
286
287
// Chain operations
288
type CleanedUp = U.NonNullable<string | number | null | undefined>; // string | number
289
type MadeNullable = U.Nullable<CleanedUp>; // string | number | null
290
291
// Conditional nullability
292
type ConditionalNullable<T, MakeNull extends boolean> =
293
MakeNull extends true ? U.Nullable<T> : U.NonNullable<T>;
294
295
type WithNull = ConditionalNullable<string | null, true>; // string | null
296
type WithoutNull = ConditionalNullable<string | null, false>; // string
297
```
298
299
### Practical Applications
300
301
Real-world usage patterns for union operations.
302
303
**Usage Examples:**
304
305
```typescript
306
import { U, O } from "ts-toolbelt";
307
308
// API response type handling
309
type SuccessResponse = { status: "success"; data: any };
310
type ErrorResponse = { status: "error"; message: string };
311
type PendingResponse = { status: "pending" };
312
type ApiResponse = SuccessResponse | ErrorResponse | PendingResponse;
313
314
type ErrorStatuses = U.Extract<ApiResponse["status"], "error" | "pending">; // "error" | "pending"
315
type NonErrorResponse = U.Exclude<ApiResponse, ErrorResponse>; // SuccessResponse | PendingResponse
316
317
// Event system
318
type ClickEvent = { type: "click"; x: number; y: number };
319
type KeyEvent = { type: "key"; key: string };
320
type ResizeEvent = { type: "resize"; width: number; height: number };
321
type Events = ClickEvent | KeyEvent | ResizeEvent;
322
323
type EventTypes = Events["type"]; // "click" | "key" | "resize"
324
type UIEvents = U.Exclude<Events, ResizeEvent>; // ClickEvent | KeyEvent
325
type OnlyResize = U.Extract<Events, ResizeEvent>; // ResizeEvent
326
327
// State management
328
type LoadingState = { type: "loading" };
329
type LoadedState = { type: "loaded"; data: any };
330
type ErrorState = { type: "error"; error: string };
331
type State = LoadingState | LoadedState | ErrorState;
332
333
type StateTypes = State["type"]; // "loading" | "loaded" | "error"
334
type DataStates = U.Exclude<State, LoadingState>; // LoadedState | ErrorState
335
type HasData = U.Has<State["type"], "loaded">; // 1
336
337
// Form validation
338
type ValidationError =
339
| { field: "email"; error: "invalid" }
340
| { field: "password"; error: "too_short" }
341
| { field: "age"; error: "required" };
342
343
type ErrorFields = ValidationError["field"]; // "email" | "password" | "age"
344
type EmailErrors = U.Extract<ValidationError, { field: "email" }>; // { field: "email"; error: "invalid" }
345
type NonEmailErrors = U.Exclude<ValidationError, { field: "email" }>; // password and age errors
346
```
347
348
## Types
349
350
```typescript { .api }
351
// Union operations work with any union types
352
// Results maintain the union structure or transform it as specified
353
```