0
# Collections and Emptiness
1
2
Specialized checks for empty and non-empty collections including arrays, objects, strings, maps, and sets. These methods help validate collection states and ensure non-empty collections for safe operations.
3
4
## Capabilities
5
6
### Array Emptiness Checking
7
8
Check if arrays are empty or contain items.
9
10
```typescript { .api }
11
/**
12
* Check if value is an empty array
13
* @param value - Value to check
14
* @returns True if value is empty array
15
*/
16
function isEmptyArray(value: unknown): value is never[];
17
18
/**
19
* Check if value is a non-empty array
20
* @param value - Value to check
21
* @returns True if value is non-empty array
22
*/
23
function isNonEmptyArray<T = unknown, Item = unknown>(value: T | Item[]): value is [Item, ...Item[]];
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
import is from '@sindresorhus/is';
30
31
is.emptyArray([]); // => true
32
is.emptyArray([1, 2, 3]); // => false
33
is.emptyArray('not array'); // => false
34
35
is.nonEmptyArray([1, 2, 3]); // => true
36
is.nonEmptyArray([]); // => false
37
38
// Type guard usage
39
function processArray(arr: unknown) {
40
if (is.nonEmptyArray(arr)) {
41
// arr is now typed as [unknown, ...unknown[]]
42
console.log('First item:', arr[0]);
43
console.log('Length:', arr.length); // guaranteed > 0
44
}
45
}
46
```
47
48
### Object Emptiness Checking
49
50
Check if objects have enumerable properties.
51
52
```typescript { .api }
53
/**
54
* Check if value is an empty object (no enumerable properties)
55
* @param value - Value to check
56
* @returns True if value is empty object
57
*/
58
function isEmptyObject<Key extends keyof any = string>(value: unknown): value is Record<Key, never>;
59
60
/**
61
* Check if value is a non-empty object (has enumerable properties)
62
* @param value - Value to check
63
* @returns True if value is non-empty object
64
*/
65
function isNonEmptyObject<Key extends keyof any = string, Value = unknown>(value: unknown): value is Record<Key, Value>;
66
```
67
68
**Usage Examples:**
69
70
```typescript
71
import is from '@sindresorhus/is';
72
73
is.emptyObject({}); // => true
74
is.emptyObject({a: 1}); // => false
75
is.emptyObject([]); // => false (arrays are not plain objects)
76
is.emptyObject(new Map()); // => false (Maps are not plain objects)
77
78
is.nonEmptyObject({a: 1}); // => true
79
is.nonEmptyObject({}); // => false
80
81
// Note: Only checks enumerable properties
82
const obj = {};
83
Object.defineProperty(obj, 'hidden', {
84
value: 42,
85
enumerable: false
86
});
87
is.emptyObject(obj); // => true (hidden property is not enumerable)
88
```
89
90
### Map Emptiness Checking
91
92
Check if Map objects are empty or contain entries.
93
94
```typescript { .api }
95
/**
96
* Check if value is an empty Map
97
* @param value - Value to check
98
* @returns True if value is empty Map
99
*/
100
function isEmptyMap(value: unknown): value is Map<never, never>;
101
102
/**
103
* Check if value is a non-empty Map
104
* @param value - Value to check
105
* @returns True if value is non-empty Map
106
*/
107
function isNonEmptyMap<Key = unknown, Value = unknown>(value: unknown): value is Map<Key, Value>;
108
```
109
110
**Usage Examples:**
111
112
```typescript
113
import is from '@sindresorhus/is';
114
115
const emptyMap = new Map();
116
const mapWithItems = new Map([['key', 'value']]);
117
118
is.emptyMap(emptyMap); // => true
119
is.emptyMap(mapWithItems); // => false
120
is.emptyMap({}); // => false
121
122
is.nonEmptyMap(mapWithItems); // => true
123
is.nonEmptyMap(emptyMap); // => false
124
125
// Type guard usage
126
function processMap(map: unknown) {
127
if (is.nonEmptyMap(map)) {
128
// map is now typed as Map<unknown, unknown> with size > 0
129
console.log('Map size:', map.size);
130
for (const [key, value] of map) {
131
console.log(key, value);
132
}
133
}
134
}
135
```
136
137
### Set Emptiness Checking
138
139
Check if Set objects are empty or contain values.
140
141
```typescript { .api }
142
/**
143
* Check if value is an empty Set
144
* @param value - Value to check
145
* @returns True if value is empty Set
146
*/
147
function isEmptySet(value: unknown): value is Set<never>;
148
149
/**
150
* Check if value is a non-empty Set
151
* @param value - Value to check
152
* @returns True if value is non-empty Set
153
*/
154
function isNonEmptySet<T = unknown>(value: unknown): value is Set<T>;
155
```
156
157
**Usage Examples:**
158
159
```typescript
160
import is from '@sindresorhus/is';
161
162
const emptySet = new Set();
163
const setWithItems = new Set([1, 2, 3]);
164
165
is.emptySet(emptySet); // => true
166
is.emptySet(setWithItems); // => false
167
is.emptySet([]); // => false
168
169
is.nonEmptySet(setWithItems); // => true
170
is.nonEmptySet(emptySet); // => false
171
172
// Type guard usage
173
function processSet(set: unknown) {
174
if (is.nonEmptySet(set)) {
175
// set is now typed as Set<unknown> with size > 0
176
console.log('Set size:', set.size);
177
for (const value of set) {
178
console.log(value);
179
}
180
}
181
}
182
```
183
184
### Array-like Type Checking
185
186
Check if a value is array-like (has a length property and indexed access).
187
188
```typescript { .api }
189
/**
190
* Check if value is array-like (has length property)
191
* @param value - Value to check
192
* @returns True if value is array-like
193
*/
194
function isArrayLike<T = unknown>(value: unknown): value is ArrayLike<T>;
195
196
type ArrayLike<T> = {
197
readonly [index: number]: T;
198
readonly length: number;
199
};
200
```
201
202
**Usage Examples:**
203
204
```typescript
205
import is from '@sindresorhus/is';
206
207
is.arrayLike([]); // => true
208
is.arrayLike('hello'); // => true (strings are array-like)
209
is.arrayLike({0: 'a', 1: 'b', length: 2}); // => true
210
is.arrayLike(document.querySelectorAll('div')); // => true (NodeList)
211
212
function processArguments() {
213
is.arrayLike(arguments); // => true
214
}
215
216
is.arrayLike({}); // => false
217
is.arrayLike(() => {}); // => false
218
```
219
220
### Tuple-like Type Checking
221
222
Check if a value matches a tuple structure with type guards.
223
224
```typescript { .api }
225
/**
226
* Check if value matches tuple structure with guards
227
* @param value - Value to check
228
* @param guards - Array of type guard functions
229
* @returns True if value matches tuple structure
230
*/
231
function isTupleLike<T extends Array<TypeGuard<unknown>>>(
232
value: unknown,
233
guards: [...T]
234
): value is ResolveTypesOfTypeGuardsTuple<T>;
235
236
type TypeGuard<T> = (value: unknown) => value is T;
237
```
238
239
**Usage Examples:**
240
241
```typescript
242
import is from '@sindresorhus/is';
243
244
// Check for [string, number] tuple
245
const guards = [is.string, is.number] as const;
246
is.tupleLike(['hello', 42], guards); // => true
247
is.tupleLike(['hello', 'world'], guards); // => false
248
is.tupleLike(['hello'], guards); // => false (wrong length)
249
250
// Type guard usage
251
function processTuple(value: unknown) {
252
if (is.tupleLike(value, [is.string, is.number, is.boolean])) {
253
// value is now typed as [string, number, boolean]
254
const [str, num, bool] = value;
255
console.log(str.toUpperCase(), num * 2, !bool);
256
}
257
}
258
259
// More complex example
260
const complexGuards = [
261
is.string,
262
(v: unknown): v is {id: number} => is.plainObject(v) && is.number((v as any).id)
263
] as const;
264
265
if (is.tupleLike(someValue, complexGuards)) {
266
// someValue is typed as [string, {id: number}]
267
console.log(someValue[0].length, someValue[1].id);
268
}
269
```
270
271
### Valid Length Checking
272
273
Check if a value is a valid length (safe integer >= 0).
274
275
```typescript { .api }
276
/**
277
* Check if value is a valid length (safe integer >= 0)
278
* @param value - Value to check
279
* @returns True if value is valid length
280
*/
281
function isValidLength(value: unknown): value is number;
282
```
283
284
**Usage Examples:**
285
286
```typescript
287
import is from '@sindresorhus/is';
288
289
is.validLength(0); // => true
290
is.validLength(5); // => true
291
is.validLength(Number.MAX_SAFE_INTEGER); // => true
292
is.validLength(-1); // => false
293
is.validLength(1.5); // => false
294
is.validLength(Number.MAX_SAFE_INTEGER + 1); // => false
295
is.validLength('5'); // => false
296
297
// Useful for validating array-like objects
298
function createArrayLike(length: unknown) {
299
if (is.validLength(length)) {
300
// length is now typed as number and guaranteed to be valid
301
const obj: any = {};
302
obj.length = length;
303
for (let i = 0; i < length; i++) {
304
obj[i] = i;
305
}
306
return obj;
307
}
308
throw new Error('Invalid length');
309
}
310
```
311
312
## Notes
313
314
- Empty/non-empty object checks only consider enumerable properties using `Object.keys()`
315
- Non-enumerable properties are ignored in object emptiness checks
316
- Array-like includes strings, NodeLists, arguments objects, and any object with numeric indices and length
317
- Tuple-like checking validates both length and type of each element
318
- Valid length is useful for creating array-like objects and validating counts
319
- All collection checks work with TypeScript type guards for compile-time type narrowing