0
# Utility Types
1
2
Advanced type operations for merging, transforming, and manipulating complex type structures including dictionaries, unions, and specialized type operations.
3
4
## Capabilities
5
6
### AsyncOrSync
7
8
Constructs a type that can be either `Type` or `PromiseLike<Type>`, useful for functions that can work with both synchronous and asynchronous values.
9
10
```typescript { .api }
11
type AsyncOrSync<Type> = Type | PromiseLike<Type>;
12
```
13
14
**Usage Example:**
15
16
```typescript
17
import type { AsyncOrSync } from "ts-essentials";
18
19
function processData<T>(data: AsyncOrSync<T>): Promise<T> {
20
return Promise.resolve(data);
21
}
22
23
// Works with both sync and async values
24
processData("hello"); // string
25
processData(Promise.resolve("hello")); // Promise<string>
26
```
27
28
### AsyncOrSyncType
29
30
Unwraps `AsyncOrSync` type to extract the underlying type.
31
32
```typescript { .api }
33
type AsyncOrSyncType<Type> = Type extends PromiseLike<infer U> ? U : Type;
34
```
35
36
### Dictionary
37
38
Constructs a required object type where property keys are `Keys` (string by default) and property values are `Type`.
39
40
```typescript { .api }
41
type Dictionary<Type, Keys extends KeyofBase = string> = {
42
[key in Keys]: Type;
43
};
44
```
45
46
**Usage Example:**
47
48
```typescript
49
import type { Dictionary } from "ts-essentials";
50
51
type StringMap = Dictionary<string>; // { [key: string]: string }
52
type NumberMap = Dictionary<number, string | number>; // { [key: string | number]: number }
53
54
const userRoles: Dictionary<string> = {
55
admin: "Administrator",
56
user: "Regular User",
57
guest: "Guest User"
58
};
59
```
60
61
### SafeDictionary
62
63
Constructs an optional object type where property keys are `Keys` (string by default) and property values are `Type`.
64
65
```typescript { .api }
66
type SafeDictionary<Type, Keys extends KeyofBase = string> = {
67
[key in Keys]?: Type;
68
};
69
```
70
71
**Usage Example:**
72
73
```typescript
74
import type { SafeDictionary } from "ts-essentials";
75
76
type OptionalSettings = SafeDictionary<boolean>;
77
// Result: { [key: string]?: boolean }
78
79
const settings: OptionalSettings = {
80
darkMode: true,
81
notifications: false
82
// Other keys are optional
83
};
84
```
85
86
### Merge
87
88
Constructs a type by picking all properties from `Object1` and `Object2`. Property values from `Object2` override property values from `Object1` when property keys are the same.
89
90
```typescript { .api }
91
type Merge<Object1, Object2> = Prettify<Omit<Object1, keyof Object2> & Object2>;
92
```
93
94
**Usage Example:**
95
96
```typescript
97
import type { Merge } from "ts-essentials";
98
99
type User = { id: number; name: string; email: string; };
100
type UserUpdate = { name: string; lastLogin: Date; };
101
102
type UpdatedUser = Merge<User, UserUpdate>;
103
// Result: { id: number; email: string; name: string; lastLogin: Date; }
104
```
105
106
### MergeN
107
108
Constructs a type by merging objects in tuple `Tuple` recursively using the `Merge` type.
109
110
```typescript { .api }
111
type MergeN<Tuple extends readonly any[]> = Tuple extends readonly [infer First, ...infer Rest]
112
? Rest extends readonly any[]
113
? Merge<First, MergeN<Rest>>
114
: First
115
: {};
116
```
117
118
**Usage Example:**
119
120
```typescript
121
import type { MergeN } from "ts-essentials";
122
123
type Base = { id: number; };
124
type Named = { name: string; };
125
type Timed = { createdAt: Date; };
126
127
type Entity = MergeN<[Base, Named, Timed]>;
128
// Result: { id: number; name: string; createdAt: Date; }
129
```
130
131
### Newable
132
133
Constructs a class type with constructor which has return type `ReturnType`.
134
135
```typescript { .api }
136
type Newable<ReturnType> = new (...args: any[]) => ReturnType;
137
```
138
139
**Usage Example:**
140
141
```typescript
142
import type { Newable } from "ts-essentials";
143
144
interface Identifiable {
145
id: string;
146
}
147
148
function createFactory<T extends Identifiable>(ctor: Newable<T>): T {
149
return new ctor();
150
}
151
```
152
153
### NonNever
154
155
Constructs a type by picking all properties from type `Type` which values don't equal to `never`.
156
157
```typescript { .api }
158
type NonNever<Type> = {
159
[Key in keyof Type as Type[Key] extends never ? never : Key]: Type[Key];
160
};
161
```
162
163
**Usage Example:**
164
165
```typescript
166
import type { NonNever } from "ts-essentials";
167
168
type Mixed = {
169
valid: string;
170
invalid: never;
171
alsoValid: number;
172
alsoInvalid: never;
173
};
174
175
type Cleaned = NonNever<Mixed>;
176
// Result: { valid: string; alsoValid: number; }
177
```
178
179
### OmitProperties
180
181
Constructs a type by picking all properties from type `Type` and removing those properties which values equal to `Value`.
182
183
```typescript { .api }
184
type OmitProperties<Type, Value> = {
185
[Key in keyof Type as Type[Key] extends Value ? never : Key]: Type[Key];
186
};
187
```
188
189
**Usage Example:**
190
191
```typescript
192
import type { OmitProperties } from "ts-essentials";
193
194
type ApiResponse = {
195
data: string;
196
error: null;
197
loading: boolean;
198
metadata: null;
199
};
200
201
type NonNullFields = OmitProperties<ApiResponse, null>;
202
// Result: { data: string; loading: boolean; }
203
```
204
205
### PickProperties
206
207
Constructs a type by picking all properties from type `Type` which values equal to `Value`.
208
209
```typescript { .api }
210
type PickProperties<Type, Value> = {
211
[Key in keyof Type as Type[Key] extends Value ? Key : never]: Type[Key];
212
};
213
```
214
215
**Usage Example:**
216
217
```typescript
218
import type { PickProperties } from "ts-essentials";
219
220
type User = {
221
id: number;
222
name: string;
223
email: string;
224
isActive: boolean;
225
isAdmin: boolean;
226
};
227
228
type BooleanFields = PickProperties<User, boolean>;
229
// Result: { isActive: boolean; isAdmin: boolean; }
230
```
231
232
### Opaque
233
234
Constructs a type which is a subset of `Type` with a specified unique token `Token`. Creates branded/nominal types.
235
236
```typescript { .api }
237
type Opaque<Type, Token> = Type & {
238
readonly __opaque__: Token;
239
};
240
```
241
242
**Usage Example:**
243
244
```typescript
245
import type { Opaque } from "ts-essentials";
246
247
type UserId = Opaque<number, "UserId">;
248
type ProductId = Opaque<number, "ProductId">;
249
250
const userId: UserId = 123 as UserId;
251
const productId: ProductId = 456 as ProductId;
252
253
// This would cause a compile error:
254
// const wrongId: UserId = productId; // Type error!
255
256
function getUserById(id: UserId): User {
257
// Implementation
258
}
259
260
getUserById(userId); // OK
261
// getUserById(productId); // Type error!
262
```
263
264
### PathValue
265
266
Constructs a path value for type `Type` and path `Path`.
267
268
```typescript { .api }
269
type PathValue<Type, Path extends string> = Path extends keyof Type
270
? Type[Path]
271
: Path extends `${infer Key}.${infer Rest}`
272
? Key extends keyof Type
273
? PathValue<Type[Key], Rest>
274
: never
275
: never;
276
```
277
278
**Usage Example:**
279
280
```typescript
281
import type { PathValue } from "ts-essentials";
282
283
type User = {
284
profile: {
285
personal: {
286
name: string;
287
age: number;
288
};
289
};
290
};
291
292
type UserName = PathValue<User, "profile.personal.name">; // string
293
type UserAge = PathValue<User, "profile.personal.age">; // number
294
```
295
296
### Paths
297
298
Constructs a union type by picking all possible paths for type `Type`.
299
300
```typescript { .api }
301
type Paths<Type> = Type extends Primitive
302
? never
303
: {
304
[Key in keyof Type]: Key extends string
305
? Type[Key] extends Primitive
306
? Key
307
: Key | `${Key}.${Paths<Type[Key]>}`
308
: never;
309
}[keyof Type];
310
```
311
312
**Usage Example:**
313
314
```typescript
315
import type { Paths } from "ts-essentials";
316
317
type User = {
318
id: number;
319
profile: {
320
name: string;
321
settings: {
322
theme: string;
323
};
324
};
325
};
326
327
type UserPaths = Paths<User>;
328
// Result: "id" | "profile" | "profile.name" | "profile.settings" | "profile.settings.theme"
329
```
330
331
### UnionToIntersection
332
333
Constructs an intersection type from union type `Union`.
334
335
```typescript { .api }
336
type UnionToIntersection<Union> = (
337
Union extends any ? (arg: Union) => void : never
338
) extends (arg: infer Intersection) => void
339
? Intersection
340
: never;
341
```
342
343
**Usage Example:**
344
345
```typescript
346
import type { UnionToIntersection } from "ts-essentials";
347
348
type A = { a: string; };
349
type B = { b: number; };
350
type C = { c: boolean; };
351
352
type Combined = UnionToIntersection<A | B | C>;
353
// Result: { a: string; } & { b: number; } & { c: boolean; }
354
// Which is equivalent to: { a: string; b: number; c: boolean; }
355
```
356
357
### ValueOf
358
359
Constructs a type for type `Type` and equals to primitive for primitives, array elements for arrays, function return type for functions, or object property values for objects.
360
361
```typescript { .api }
362
type ValueOf<Type> = Type[keyof Type];
363
```
364
365
**Usage Example:**
366
367
```typescript
368
import type { ValueOf } from "ts-essentials";
369
370
type User = {
371
id: number;
372
name: string;
373
isActive: boolean;
374
};
375
376
type UserValue = ValueOf<User>; // number | string | boolean
377
378
const values: UserValue[] = [123, "Alice", true];
379
```
380
381
### XOR
382
383
Constructs a type which is assignable to either `Type1` or `Type2` but not both. Supports up to 50 generic types.
384
385
```typescript { .api }
386
type XOR<Type1, Type2> =
387
| (Type1 & { [K in keyof Type2]?: never })
388
| (Type2 & { [K in keyof Type1]?: never });
389
```
390
391
**Usage Example:**
392
393
```typescript
394
import type { XOR } from "ts-essentials";
395
396
type LoginByEmail = { email: string; };
397
type LoginByUsername = { username: string; };
398
399
type LoginCredentials = XOR<LoginByEmail, LoginByUsername>;
400
401
// Valid:
402
const emailLogin: LoginCredentials = { email: "user@example.com" };
403
const usernameLogin: LoginCredentials = { username: "user123" };
404
405
// Invalid (would cause compile error):
406
// const invalidLogin: LoginCredentials = { email: "user@example.com", username: "user123" };
407
```
408
409
## Types
410
411
```typescript { .api }
412
/** @deprecated Use ValueOf instead */
413
type DictionaryValues<Type> = Type[keyof Type];
414
```