0
# TypeScript Utilities
1
2
General-purpose TypeScript utility types for advanced type manipulation, conditional type logic, and media type handling.
3
4
## Capabilities
5
6
### Key Filtering Utilities
7
8
#### Filter Keys
9
10
Find first match of multiple keys from an object type.
11
12
```typescript { .api }
13
/**
14
* Find first match of multiple keys
15
*/
16
type FilterKeys<Obj, Matchers> = Obj[keyof Obj & Matchers];
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import type { FilterKeys } from "openapi-typescript-helpers";
23
24
// Extract values by key pattern
25
type ApiResponse = {
26
"application/json": { data: User };
27
"application/xml": string;
28
"text/plain": string;
29
};
30
31
// Filter by specific key
32
type JsonContent = FilterKeys<ApiResponse, "application/json">; // { data: User }
33
34
// Filter by key pattern (using template literal types)
35
type ApplicationTypes = FilterKeys<ApiResponse, `application/${string}`>;
36
// { data: User } | string
37
38
// Multiple object example
39
type StatusResponses = {
40
200: { success: true };
41
400: { error: string };
42
404: { error: string };
43
};
44
45
type ErrorResponses = FilterKeys<StatusResponses, 400 | 404>; // { error: string }
46
```
47
48
#### Get Value with Default (Deprecated)
49
50
Get the type of a value of an input object with a given key, with fallback default.
51
52
```typescript { .api }
53
/**
54
* @deprecated Use `FilterKeys` instead
55
* Get the type of a value of an input object with a given key. If the key is
56
* not found, return a default type. Works with unions of objects too.
57
*/
58
type GetValueWithDefault<Obj, KeyPattern, Default> = Obj extends any
59
? FilterKeys<Obj, KeyPattern> extends never
60
? Default
61
: FilterKeys<Obj, KeyPattern>
62
: never;
63
```
64
65
### Media Type Utilities
66
67
#### Media Type
68
69
Return any string/string media type pattern.
70
71
```typescript { .api }
72
/**
73
* Return any `[string]/[string]` media type (important because openapi-fetch allows any content response, not just JSON-like)
74
*/
75
type MediaType = `${string}/${string}`;
76
```
77
78
**Usage Examples:**
79
80
```typescript
81
import type { MediaType } from "openapi-typescript-helpers";
82
83
// Type-safe media type validation
84
function isValidMediaType(type: string): type is MediaType {
85
return /^[^\/]+\/[^\/]+$/.test(type);
86
}
87
88
// Generic content type handling
89
type ContentTypeMap<T extends MediaType> = {
90
[K in T]: unknown;
91
};
92
93
type ApiContent = ContentTypeMap<"application/json" | "text/plain">;
94
// { "application/json": unknown; "text/plain": unknown }
95
```
96
97
#### JSON-Like Media Types
98
99
Return media types containing "json".
100
101
```typescript { .api }
102
/**
103
* Return any media type containing "json" (works for "application/json", "application/vnd.api+json", "application/vnd.oai.openapi+json")
104
*/
105
type JSONLike<T> = FilterKeys<T, `${string}/json`>;
106
```
107
108
**Usage Examples:**
109
110
```typescript
111
import type { JSONLike } from "openapi-typescript-helpers";
112
113
// Extract JSON-compatible content types
114
type ContentTypes = {
115
"application/json": { data: User };
116
"application/vnd.api+json": { data: User[] };
117
"application/xml": string;
118
"text/plain": string;
119
"text/json": { message: string };
120
};
121
122
type JsonOnlyContent = JSONLike<ContentTypes>;
123
// { data: User } | { data: User[] } | { message: string }
124
125
// Use in API response handling
126
function handleJsonResponse<T>(content: JSONLike<T>): void {
127
// Only JSON-like content types allowed
128
}
129
```
130
131
### Required Keys Utilities
132
133
#### Required Keys Helper
134
135
Internal helper for required key detection.
136
137
```typescript { .api }
138
/**
139
* Helper to get the required keys of an object. If no keys are required, will be `undefined` with strictNullChecks enabled, else `never`
140
*/
141
type RequiredKeysOfHelper<T> = {
142
[K in keyof T]: {} extends Pick<T, K> ? never : K;
143
}[keyof T];
144
```
145
146
#### Required Keys Of
147
148
Get the required keys of an object, or never if no keys are required.
149
150
```typescript { .api }
151
/**
152
* Get the required keys of an object, or `never` if no keys are required
153
*/
154
type RequiredKeysOf<T> = RequiredKeysOfHelper<T> extends undefined ? never : RequiredKeysOfHelper<T>;
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
import type { RequiredKeysOf } from "openapi-typescript-helpers";
161
162
// Check required keys in object types
163
type User = {
164
id: string;
165
name: string;
166
email?: string;
167
profile?: UserProfile;
168
};
169
170
type UserRequiredKeys = RequiredKeysOf<User>; // "id" | "name"
171
172
// Use in validation
173
type ValidateRequired<T, K extends RequiredKeysOf<T>> = {
174
[P in K]: T[P];
175
};
176
177
type RequiredUserFields = ValidateRequired<User, RequiredKeysOf<User>>;
178
// { id: string; name: string }
179
180
// Check if object has required fields
181
type HasRequired<T> = RequiredKeysOf<T> extends never ? false : true;
182
183
type UserHasRequired = HasRequired<User>; // true
184
type EmptyObjectHasRequired = HasRequired<{}>; // false
185
```
186
187
### Deprecated Utilities
188
189
#### Find Required Keys (Deprecated)
190
191
Filter objects that have required keys.
192
193
```typescript { .api }
194
/**
195
* Filter objects that have required keys
196
* @deprecated Use `RequiredKeysOf` instead
197
*/
198
type FindRequiredKeys<T, K extends keyof T> = K extends unknown ? (undefined extends T[K] ? never : K) : K;
199
```
200
201
#### Has Required Keys (Deprecated)
202
203
Check if object contains required keys.
204
205
```typescript { .api }
206
/**
207
* Does this object contain required keys?
208
* @deprecated Use `RequiredKeysOf` instead
209
*/
210
type HasRequiredKeys<T> = FindRequiredKeys<T, keyof T>;
211
```
212
213
**Migration Examples:**
214
215
```typescript
216
// Old approach (deprecated)
217
type OldRequiredCheck<T> = HasRequiredKeys<T> extends never ? false : true;
218
219
// New approach (recommended)
220
type NewRequiredCheck<T> = RequiredKeysOf<T> extends never ? false : true;
221
222
// Old required key extraction (deprecated)
223
type OldRequiredKeys<T> = FindRequiredKeys<T, keyof T>;
224
225
// New required key extraction (recommended)
226
type NewRequiredKeys<T> = RequiredKeysOf<T>;
227
```
228
229
## Advanced Usage Patterns
230
231
### Combining Utilities
232
233
```typescript
234
import type {
235
FilterKeys,
236
JSONLike,
237
RequiredKeysOf,
238
MediaType
239
} from "openapi-typescript-helpers";
240
241
// Complex content type filtering
242
type ApiResponseContent = {
243
"application/json": { data: User; meta: Metadata };
244
"application/vnd.api+json": { data: User[]; included: Resource[] };
245
"application/xml": string;
246
"text/html": string;
247
};
248
249
// Extract JSON content and determine required fields
250
type JsonContent = JSONLike<ApiResponseContent>;
251
type JsonRequiredKeys = RequiredKeysOf<JsonContent>;
252
253
// Create type-safe content handler
254
type ContentHandler<T extends MediaType> = (
255
content: FilterKeys<ApiResponseContent, T>
256
) => void;
257
258
// Use with specific media types
259
const handleJson: ContentHandler<"application/json"> = (content) => {
260
// content is properly typed as { data: User; meta: Metadata }
261
console.log(content.data);
262
};
263
```
264
265
### Error Handling with Utility Types
266
267
```typescript
268
import type { FilterKeys, RequiredKeysOf } from "openapi-typescript-helpers";
269
270
// Create error types with required field validation
271
type ApiError = {
272
code: string;
273
message: string;
274
details?: Record<string, unknown>;
275
};
276
277
type RequiredErrorFields = RequiredKeysOf<ApiError>; // "code" | "message"
278
279
// Ensure error objects have required fields
280
function createError<T extends Record<RequiredErrorFields, any>>(error: T): T {
281
return error;
282
}
283
284
// Type-safe error with all required fields
285
const validError = createError({
286
code: "VALIDATION_ERROR",
287
message: "Invalid input provided",
288
details: { field: "email" }
289
});
290
```