0
# Async and Promises
1
2
Type checking for promises, async functions, generators, and iterables including both synchronous and asynchronous variants.
3
4
## Capabilities
5
6
### Promise Type Checking
7
8
Check if a value is a promise-like object or native Promise.
9
10
```typescript { .api }
11
/**
12
* Check if value is promise-like (has .then() and .catch() methods)
13
* @param value - Value to check
14
* @returns True if value is promise-like
15
*/
16
function isPromise<T = unknown>(value: unknown): value is Promise<T>;
17
18
/**
19
* Check if value is a native Promise
20
* @param value - Value to check
21
* @returns True if value is native Promise
22
*/
23
function isNativePromise<T = unknown>(value: unknown): value is Promise<T>;
24
```
25
26
**Usage Examples:**
27
28
```typescript
29
import is from '@sindresorhus/is';
30
31
is.promise(Promise.resolve(42)); // => true
32
is.promise(new Promise(() => {})); // => true
33
34
// Promise-like objects
35
const thenable = {
36
then: (resolve: Function) => resolve(42),
37
catch: (reject: Function) => {}
38
};
39
is.promise(thenable); // => true
40
41
// Native Promise checking
42
is.nativePromise(Promise.resolve(42)); // => true
43
is.nativePromise(thenable); // => false
44
45
// Type guard usage
46
async function handlePromise(value: unknown) {
47
if (is.promise(value)) {
48
// value is now typed as Promise<unknown>
49
const result = await value;
50
console.log(result);
51
}
52
}
53
```
54
55
### Async Function Type Checking
56
57
Check if a value is an async function.
58
59
```typescript { .api }
60
/**
61
* Check if value is an async function
62
* @param value - Value to check
63
* @returns True if value is async function
64
*/
65
function isAsyncFunction<T = unknown>(value: unknown): value is ((...arguments_: any[]) => Promise<T>);
66
```
67
68
**Usage Examples:**
69
70
```typescript
71
import is from '@sindresorhus/is';
72
73
is.asyncFunction(async () => {}); // => true
74
is.asyncFunction(async function() {}); // => true
75
is.asyncFunction(() => {}); // => false
76
is.asyncFunction(function() {}); // => false
77
78
// Type guard usage
79
async function executeAsync(fn: unknown) {
80
if (is.asyncFunction(fn)) {
81
// fn is now typed as async function
82
const result = await fn();
83
console.log(result);
84
}
85
}
86
```
87
88
### Generator Type Checking
89
90
Check if a value is a generator object.
91
92
```typescript { .api }
93
/**
94
* Check if value is a generator
95
* @param value - Value to check
96
* @returns True if value is generator
97
*/
98
function isGenerator(value: unknown): value is Generator;
99
```
100
101
**Usage Examples:**
102
103
```typescript
104
import is from '@sindresorhus/is';
105
106
function* myGenerator() {
107
yield 1;
108
yield 2;
109
}
110
111
const gen = myGenerator();
112
is.generator(gen); // => true
113
is.generator(myGenerator); // => false (function, not generator instance)
114
115
// Type guard usage
116
function processGenerator(value: unknown) {
117
if (is.generator(value)) {
118
// value is now typed as Generator
119
const { value: firstValue, done } = value.next();
120
console.log(firstValue, done);
121
}
122
}
123
```
124
125
### Generator Function Type Checking
126
127
Check if a value is a generator function.
128
129
```typescript { .api }
130
/**
131
* Check if value is a generator function
132
* @param value - Value to check
133
* @returns True if value is generator function
134
*/
135
function isGeneratorFunction(value: unknown): value is GeneratorFunction;
136
```
137
138
**Usage Examples:**
139
140
```typescript
141
import is from '@sindresorhus/is';
142
143
function* myGenerator() {
144
yield 1;
145
}
146
147
is.generatorFunction(myGenerator); // => true
148
is.generatorFunction(myGenerator()); // => false (generator instance)
149
is.generatorFunction(() => {}); // => false
150
151
// Type guard usage
152
function createGenerator(fn: unknown) {
153
if (is.generatorFunction(fn)) {
154
// fn is now typed as GeneratorFunction
155
const generator = fn();
156
return generator;
157
}
158
}
159
```
160
161
### Async Generator Type Checking
162
163
Check if a value is an async generator object.
164
165
```typescript { .api }
166
/**
167
* Check if value is an async generator
168
* @param value - Value to check
169
* @returns True if value is async generator
170
*/
171
function isAsyncGenerator(value: unknown): value is AsyncGenerator;
172
```
173
174
**Usage Examples:**
175
176
```typescript
177
import is from '@sindresorhus/is';
178
179
async function* myAsyncGenerator() {
180
yield 1;
181
yield 2;
182
}
183
184
const asyncGen = myAsyncGenerator();
185
is.asyncGenerator(asyncGen); // => true
186
187
// Regular generator is not async generator
188
function* regularGen() { yield 1; }
189
is.asyncGenerator(regularGen()); // => false
190
191
// Type guard usage
192
async function processAsyncGenerator(value: unknown) {
193
if (is.asyncGenerator(value)) {
194
// value is now typed as AsyncGenerator
195
const { value: firstValue, done } = await value.next();
196
console.log(firstValue, done);
197
}
198
}
199
```
200
201
### Async Generator Function Type Checking
202
203
Check if a value is an async generator function.
204
205
```typescript { .api }
206
/**
207
* Check if value is an async generator function
208
* @param value - Value to check
209
* @returns True if value is async generator function
210
*/
211
function isAsyncGeneratorFunction(value: unknown): value is AsyncGeneratorFunction;
212
```
213
214
**Usage Examples:**
215
216
```typescript
217
import is from '@sindresorhus/is';
218
219
async function* myAsyncGenerator() {
220
yield 1;
221
}
222
223
is.asyncGeneratorFunction(myAsyncGenerator); // => true
224
is.asyncGeneratorFunction(myAsyncGenerator()); // => false (async generator instance)
225
226
function* regularGenerator() { yield 1; }
227
is.asyncGeneratorFunction(regularGenerator); // => false
228
229
// Type guard usage
230
function createAsyncGenerator(fn: unknown) {
231
if (is.asyncGeneratorFunction(fn)) {
232
// fn is now typed as AsyncGeneratorFunction
233
const asyncGenerator = fn();
234
return asyncGenerator;
235
}
236
}
237
```
238
239
### Iterable Type Checking
240
241
Check if a value is iterable (has Symbol.iterator).
242
243
```typescript { .api }
244
/**
245
* Check if value is iterable
246
* @param value - Value to check
247
* @returns True if value is iterable
248
*/
249
function isIterable<T = unknown>(value: unknown): value is Iterable<T>;
250
```
251
252
**Usage Examples:**
253
254
```typescript
255
import is from '@sindresorhus/is';
256
257
is.iterable([]); // => true
258
is.iterable('hello'); // => true
259
is.iterable(new Set()); // => true
260
is.iterable(new Map()); // => true
261
is.iterable({}); // => false
262
263
function* generator() { yield 1; }
264
is.iterable(generator()); // => true
265
266
// Type guard usage
267
function processIterable(value: unknown) {
268
if (is.iterable(value)) {
269
// value is now typed as Iterable<unknown>
270
for (const item of value) {
271
console.log(item);
272
}
273
}
274
}
275
```
276
277
### Async Iterable Type Checking
278
279
Check if a value is async iterable (has Symbol.asyncIterator).
280
281
```typescript { .api }
282
/**
283
* Check if value is async iterable
284
* @param value - Value to check
285
* @returns True if value is async iterable
286
*/
287
function isAsyncIterable<T = unknown>(value: unknown): value is AsyncIterable<T>;
288
```
289
290
**Usage Examples:**
291
292
```typescript
293
import is from '@sindresorhus/is';
294
295
async function* asyncGenerator() {
296
yield 1;
297
yield 2;
298
}
299
300
is.asyncIterable(asyncGenerator()); // => true
301
is.asyncIterable([]); // => false (regular arrays are not async iterable)
302
303
// Custom async iterable
304
const customAsyncIterable = {
305
async *[Symbol.asyncIterator]() {
306
yield 1;
307
yield 2;
308
}
309
};
310
is.asyncIterable(customAsyncIterable); // => true
311
312
// Type guard usage
313
async function processAsyncIterable(value: unknown) {
314
if (is.asyncIterable(value)) {
315
// value is now typed as AsyncIterable<unknown>
316
for await (const item of value) {
317
console.log(item);
318
}
319
}
320
}
321
```
322
323
### Observable Type Checking
324
325
Check if a value is an Observable-like object.
326
327
```typescript { .api }
328
/**
329
* Check if value is Observable-like
330
* @param value - Value to check
331
* @returns True if value is Observable-like
332
*/
333
function isObservable(value: unknown): value is ObservableLike;
334
335
type ObservableLike = {
336
subscribe(observer: (value: unknown) => void): void;
337
[Symbol.observable](): ObservableLike;
338
};
339
```
340
341
**Usage Examples:**
342
343
```typescript
344
import is from '@sindresorhus/is';
345
import { Observable } from 'rxjs';
346
347
const observable = new Observable(subscriber => {
348
subscriber.next(1);
349
subscriber.complete();
350
});
351
352
is.observable(observable); // => true
353
354
// Custom observable-like
355
const customObservable = {
356
subscribe: (observer: Function) => observer(42),
357
[Symbol.observable]: function() { return this; }
358
};
359
is.observable(customObservable); // => true
360
361
is.observable(Promise.resolve(42)); // => false
362
363
// Type guard usage
364
function processObservable(value: unknown) {
365
if (is.observable(value)) {
366
// value is now typed as ObservableLike
367
value.subscribe(result => console.log(result));
368
}
369
}
370
```
371
372
## Usage Patterns
373
374
### Promise Handling
375
376
```typescript
377
import is from '@sindresorhus/is';
378
379
async function handleAsyncValue(value: unknown) {
380
if (is.promise(value)) {
381
const result = await value;
382
console.log('Promise resolved:', result);
383
} else if (is.asyncFunction(value)) {
384
const result = await value();
385
console.log('Async function result:', result);
386
}
387
}
388
```
389
390
### Generator Processing
391
392
```typescript
393
import is from '@sindresorhus/is';
394
395
function processGeneratorValue(value: unknown) {
396
if (is.generator(value)) {
397
// Process regular generator
398
let result = value.next();
399
while (!result.done) {
400
console.log(result.value);
401
result = value.next();
402
}
403
} else if (is.asyncGenerator(value)) {
404
// Process async generator
405
processAsyncGenerator(value);
406
}
407
}
408
409
async function processAsyncGenerator(gen: AsyncGenerator) {
410
let result = await gen.next();
411
while (!result.done) {
412
console.log(result.value);
413
result = await gen.next();
414
}
415
}
416
```
417
418
## Notes
419
420
- `is.promise()` accepts both native Promises and thenable objects (with `.then()` and `.catch()`)
421
- Use `is.nativePromise()` when you specifically need native Promise instances
422
- Generators and generator functions are different - one creates the other
423
- Async generators require `for await...of` loops or manual `await gen.next()` calls
424
- Observable checking looks for Symbol.observable or @@observable properties
425
- All async type checks work with TypeScript type guards for compile-time type narrowing