0
# Object Type Checking
1
2
Comprehensive object type validation including plain object detection, empty/full object checks, and object-like detection. These functions provide crucial distinctions between different types of objects in JavaScript.
3
4
## Capabilities
5
6
### Object Type Checking
7
8
Returns whether the payload is a plain JavaScript object. This is an alias for `isPlainObject`.
9
10
```typescript { .api }
11
/**
12
* Returns whether the payload is a plain JavaScript object (excluding special classes
13
* or objects with other prototypes). This is an alias for isPlainObject.
14
* @param payload - Value to check
15
* @returns Type guard indicating if payload is plain object
16
*/
17
function isObject(payload: unknown): payload is PlainObject;
18
```
19
20
**Usage Examples:**
21
22
```typescript
23
import { isObject } from "is-what";
24
25
// Plain objects
26
isObject({}); // true
27
isObject({ name: "John", age: 30 }); // true
28
29
// Not plain objects
30
isObject([]); // false (array)
31
isObject(new Date()); // false (Date instance)
32
isObject(new Map()); // false (Map instance)
33
isObject(/regex/); // false (RegExp instance)
34
isObject(() => {}); // false (function)
35
isObject(null); // false (null)
36
isObject("string"); // false
37
isObject(123); // false
38
39
if (isObject(data)) {
40
// TypeScript knows data is PlainObject
41
console.log(Object.keys(data)); // Safe to use Object methods
42
}
43
```
44
45
### Plain Object Detection
46
47
Returns whether the payload is a plain JavaScript object (excluding special classes or objects with other prototypes). This is one of the most important functions for distinguishing plain objects from class instances.
48
49
```typescript { .api }
50
/**
51
* Returns whether the payload is a plain JavaScript object (excluding special classes
52
* or objects with other prototypes)
53
* @param payload - Value to check
54
* @returns Type guard indicating if payload is plain object
55
*/
56
function isPlainObject(payload: unknown): payload is PlainObject;
57
58
type PlainObject = { [key in string | number | symbol]: unknown };
59
```
60
61
**Usage Examples:**
62
63
```typescript
64
import { isPlainObject } from "is-what";
65
66
// Plain objects
67
isPlainObject({}); // true
68
isPlainObject({ name: "John", age: 30 }); // true
69
isPlainObject(Object.create(null)); // true (no prototype)
70
isPlainObject(Object.create(Object.prototype)); // true
71
72
// Not plain objects
73
isPlainObject([]); // false (array)
74
isPlainObject(new Date()); // false (Date instance)
75
isPlainObject(new Map()); // false (Map instance)
76
isPlainObject(/regex/); // false (RegExp instance)
77
isPlainObject(() => {}); // false (function)
78
79
class MyClass {
80
constructor(public name: string) {}
81
}
82
isPlainObject(new MyClass("test")); // false (class instance)
83
84
// Practical usage
85
function mergeConfig(userConfig: unknown, defaultConfig: object) {
86
if (isPlainObject(userConfig)) {
87
// Safe to merge - it's a plain object
88
return { ...defaultConfig, ...userConfig };
89
}
90
91
throw new Error("Config must be a plain object");
92
}
93
94
// JSON-like validation
95
function isJsonSerializable(value: unknown): boolean {
96
if (isPlainObject(value)) {
97
// Check all properties recursively
98
return Object.values(value).every(isJsonSerializable);
99
}
100
// Add other JSON-compatible type checks...
101
return false;
102
}
103
```
104
105
### Any Object Detection
106
107
Returns whether the payload is any kind of object with Object prototype (but not arrays, dates, etc.).
108
109
```typescript { .api }
110
/**
111
* Returns whether the payload is any kind of object (including special classes or objects with
112
* different prototypes)
113
* @param payload - Value to check
114
* @returns Type guard indicating if payload is any object
115
*/
116
function isAnyObject(payload: unknown): payload is PlainObject;
117
```
118
119
**Usage Examples:**
120
121
```typescript
122
import { isAnyObject } from "is-what";
123
124
isAnyObject({}); // true
125
isAnyObject([]); // true
126
isAnyObject(new Date()); // true
127
isAnyObject(new Map()); // true
128
isAnyObject(/regex/); // true
129
isAnyObject(() => {}); // true
130
isAnyObject(null); // false
131
isAnyObject("string"); // false
132
isAnyObject(123); // false
133
134
// Useful for broad object checks
135
function processObjectData(input: unknown) {
136
if (isAnyObject(input)) {
137
// Any object type can be processed
138
console.log("Processing object:", Object.keys(input));
139
}
140
}
141
```
142
143
### Object-Like Detection
144
145
Returns whether the payload is an object like a type passed in generics. This is a generic function for type-safe object checking.
146
147
```typescript { .api }
148
/**
149
* Returns whether the payload is an object like a type passed in < >
150
* Usage: isObjectLike<{id: any}>(payload) // will make sure it's an object and has an `id` prop.
151
* @template T This must be passed in < >
152
* @param payload - Value to check
153
* @returns Type guard indicating if payload matches the generic type
154
*/
155
function isObjectLike<T extends PlainObject>(payload: unknown): payload is T;
156
```
157
158
**Usage Examples:**
159
160
```typescript
161
import { isObjectLike } from "is-what";
162
163
// Generic type checking
164
interface User {
165
id: string;
166
name: string;
167
}
168
169
if (isObjectLike<User>(data)) {
170
// TypeScript knows data has User shape, but doesn't validate properties
171
// This is mainly for type assertion purposes
172
}
173
174
// More practical usage for ensuring object structure
175
function processUserData(input: unknown) {
176
if (isObjectLike<{ id: string; name: string }>(input)) {
177
// TypeScript knows input has id and name properties
178
return `User: ${input.name} (${input.id})`;
179
}
180
181
throw new Error("Invalid user data structure");
182
}
183
```
184
185
### Empty Object Checking
186
187
Returns whether the payload is an empty plain object with no enumerable properties.
188
189
```typescript { .api }
190
/**
191
* Returns whether the payload is an empty object (excluding special classes or objects
192
* with other prototypes)
193
* @param payload - Value to check
194
* @returns Type guard indicating if payload is empty plain object
195
*/
196
function isEmptyObject(payload: unknown): payload is { [K in string | symbol | number]: never };
197
```
198
199
**Usage Examples:**
200
201
```typescript
202
import { isEmptyObject } from "is-what";
203
204
isEmptyObject({}); // true
205
isEmptyObject({ name: "John" }); // false
206
isEmptyObject([]); // false (not a plain object)
207
isEmptyObject(new Date()); // false (not a plain object)
208
isEmptyObject(null); // false
209
isEmptyObject(""); // false
210
211
// Practical usage
212
function validateConfigObject(config: unknown) {
213
if (isEmptyObject(config)) {
214
console.log("No configuration provided, using defaults");
215
return getDefaultConfig();
216
}
217
218
// Process non-empty config
219
return config;
220
}
221
222
// Combined with plain object check
223
function processUserInput(input: unknown) {
224
if (isPlainObject(input)) {
225
if (isEmptyObject(input)) {
226
return { error: "Configuration cannot be empty" };
227
}
228
229
return { success: true, config: input };
230
}
231
232
return { error: "Input must be a plain object" };
233
}
234
```
235
236
### Full Object Checking
237
238
Returns whether the payload is a plain object with at least one enumerable property.
239
240
```typescript { .api }
241
/**
242
* Returns whether the payload is a plain object with at least one property (excluding special classes or objects
243
* with other prototypes)
244
* @param payload - Value to check
245
* @returns Type guard indicating if payload is non-empty plain object
246
*/
247
function isFullObject(payload: unknown): payload is PlainObject;
248
```
249
250
**Usage Examples:**
251
252
```typescript
253
import { isFullObject } from "is-what";
254
255
isFullObject({ name: "John" }); // true
256
isFullObject({ 0: "a", 1: "b" }); // true
257
isFullObject([1, 2, 3]); // false (not a plain object)
258
isFullObject({}); // false
259
isFullObject([]); // false
260
isFullObject(null); // false
261
isFullObject("string"); // false
262
263
// Validation pattern
264
function requireNonEmptyObject(obj: unknown, fieldName: string) {
265
if (!isFullObject(obj)) {
266
throw new Error(`${fieldName} must be a non-empty object`);
267
}
268
269
return obj;
270
}
271
```
272
273
## Combined Object Validation Patterns
274
275
```typescript
276
import {
277
isObject,
278
isPlainObject,
279
isAnyObject,
280
isEmptyObject,
281
isFullObject
282
} from "is-what";
283
284
function analyzeObject(value: unknown) {
285
if (!isObject(value)) {
286
return "Not an object";
287
}
288
289
const characteristics = [];
290
291
if (isPlainObject(value)) {
292
characteristics.push("plain object");
293
} else {
294
characteristics.push("special object");
295
}
296
297
if (isEmptyObject(value)) {
298
characteristics.push("empty");
299
} else if (isFullObject(value)) {
300
const keys = Object.keys(value);
301
characteristics.push(`${keys.length} properties`);
302
}
303
304
return characteristics.join(", ");
305
}
306
307
// Object processing pipeline
308
function processObjectInput(input: unknown) {
309
// Broad object check
310
if (!isAnyObject(input)) {
311
throw new Error("Input must be an object");
312
}
313
314
// Handle different object types
315
if (isPlainObject(input)) {
316
if (isEmptyObject(input)) {
317
return { type: "plain", empty: true, processed: {} };
318
}
319
320
if (isFullObject(input)) {
321
// Safe to iterate over properties
322
const processed = Object.fromEntries(
323
Object.entries(input).map(([key, value]) => [
324
key,
325
typeof value === 'string' ? value.trim() : value
326
])
327
);
328
329
return {
330
type: "plain",
331
empty: false,
332
keys: Object.keys(input),
333
processed
334
};
335
}
336
}
337
338
// Handle special objects (arrays, dates, etc.)
339
return {
340
type: "special",
341
constructor: input.constructor?.name || "Unknown",
342
processed: input
343
};
344
}
345
346
// Type-safe object operations
347
function safeObjectOperations(obj: unknown) {
348
if (isPlainObject(obj)) {
349
const keys = Object.keys(obj);
350
const values = Object.values(obj);
351
352
return {
353
isPlain: true,
354
isEmpty: isEmptyObject(obj),
355
keyCount: keys.length,
356
keys,
357
values,
358
entries: Object.entries(obj)
359
};
360
}
361
362
if (isAnyObject(obj)) {
363
return {
364
isPlain: false,
365
type: obj.constructor?.name || "Object",
366
toString: obj.toString?.() || "[object Object]"
367
};
368
}
369
370
return null;
371
}
372
373
// Example usage
374
analyzeObject({}); // "plain object, empty"
375
analyzeObject({ name: "John", age: 30 }); // "plain object, 2 properties"
376
analyzeObject([]); // "special object, empty"
377
analyzeObject([1, 2, 3]); // "special object, 3 properties"
378
analyzeObject(new Date()); // "special object, 0 properties"
379
analyzeObject("not object"); // "Not an object"
380
381
const result = processObjectInput({ name: " John ", age: 30 });
382
// Returns: {
383
// type: "plain",
384
// empty: false,
385
// keys: ["name", "age"],
386
// processed: { name: "John", age: 30 }
387
// }
388
```
389
390
## Types
391
392
```typescript { .api }
393
type PlainObject = { [key in string | number | symbol]: unknown };
394
```