0
# Advanced Type Checking
1
2
Advanced utilities for function detection, primitive checking, iterable validation, and composite type checking. These functions provide higher-level type analysis capabilities.
3
4
## Capabilities
5
6
### Function Detection
7
8
Returns whether the payload is a function (regular or async).
9
10
```typescript { .api }
11
/**
12
* Returns whether the payload is a function (regular or async)
13
* @param payload - Value to check
14
* @returns Type guard indicating if payload is function
15
*/
16
function isFunction(payload: unknown): payload is AnyFunction;
17
18
type AnyFunction = (...args: any[]) => any;
19
type AnyAsyncFunction = (...args: unknown[]) => Promise<unknown>;
20
```
21
22
**Usage Examples:**
23
24
```typescript
25
import { isFunction } from "is-what";
26
27
// Regular functions
28
isFunction(function() {}); // true
29
isFunction(() => {}); // true
30
isFunction(console.log); // true
31
32
// Async functions
33
isFunction(async function() {}); // true
34
isFunction(async () => {}); // true
35
36
// Methods
37
class MyClass {
38
method() {}
39
}
40
const obj = new MyClass();
41
isFunction(obj.method); // true
42
43
// Not functions
44
isFunction("function"); // false
45
isFunction({}); // false
46
isFunction(null); // false
47
48
if (isFunction(callback)) {
49
// TypeScript knows callback is a function
50
const result = callback(arg1, arg2);
51
}
52
53
// Practical usage
54
function executeCallback(callback: unknown, ...args: unknown[]) {
55
if (isFunction(callback)) {
56
return callback(...args);
57
}
58
59
throw new Error("Callback must be a function");
60
}
61
62
// Higher-order function validation
63
function createValidator(validator: unknown) {
64
if (!isFunction(validator)) {
65
throw new Error("Validator must be a function");
66
}
67
68
return (value: unknown) => validator(value);
69
}
70
```
71
72
### Primitive Type Checking
73
74
Returns whether the payload is a primitive type (Boolean, Null, Undefined, Number, String, Symbol, or BigInt).
75
76
```typescript { .api }
77
/**
78
* Returns whether the payload is a primitive type
79
* (Boolean | Null | Undefined | Number | String | Symbol | BigInt)
80
* @param payload - Value to check
81
* @returns Type guard indicating if payload is primitive
82
*/
83
function isPrimitive(
84
payload: unknown
85
): payload is boolean | null | undefined | number | string | symbol | bigint;
86
```
87
88
**Usage Examples:**
89
90
```typescript
91
import { isPrimitive } from "is-what";
92
93
// Primitive values
94
isPrimitive(true); // true
95
isPrimitive(42); // true
96
isPrimitive("hello"); // true
97
isPrimitive(null); // true
98
isPrimitive(undefined); // true
99
isPrimitive(Symbol("test")); // true
100
isPrimitive(123n); // true
101
102
// Non-primitive values
103
isPrimitive({}); // false
104
isPrimitive([]); // false
105
isPrimitive(new Date()); // false
106
isPrimitive(() => {}); // false
107
108
// Practical usage
109
function serializeValue(value: unknown) {
110
if (isPrimitive(value)) {
111
// Safe to serialize directly
112
return JSON.stringify(value);
113
}
114
115
// Handle complex objects
116
return JSON.stringify(value, null, 2);
117
}
118
119
// Type categorization
120
function categorizeValue(value: unknown) {
121
if (isPrimitive(value)) {
122
return {
123
category: "primitive",
124
type: typeof value,
125
value: value
126
};
127
}
128
129
return {
130
category: "object",
131
type: value?.constructor?.name || "Object",
132
value: value
133
};
134
}
135
```
136
137
### Iterable Detection
138
139
Returns whether the payload is an iterable (regular or async).
140
141
```typescript { .api }
142
/**
143
* Returns whether the payload is an iterable (regular or async)
144
* @param payload - Value to check
145
* @returns Type guard indicating if payload is iterable
146
*/
147
function isIterable(payload: unknown): payload is Iterable<unknown>;
148
```
149
150
**Usage Examples:**
151
152
```typescript
153
import { isIterable } from "is-what";
154
155
// Iterable types
156
isIterable([]); // true (arrays)
157
isIterable("hello"); // true (strings)
158
isIterable(new Set([1, 2, 3])); // true
159
isIterable(new Map([["a", 1]])); // true
160
isIterable(function*() { yield 1; }()); // true (generators)
161
162
// Custom iterables
163
const customIterable = {
164
*[Symbol.iterator]() {
165
yield 1;
166
yield 2;
167
yield 3;
168
}
169
};
170
isIterable(customIterable); // true
171
172
// Not iterable
173
isIterable({}); // false
174
isIterable(123); // false
175
isIterable(null); // false
176
177
if (isIterable(collection)) {
178
// TypeScript knows collection is iterable
179
for (const item of collection) {
180
console.log(item);
181
}
182
183
// Can use spread operator
184
const array = [...collection];
185
}
186
187
// Practical usage
188
function processIterable(input: unknown) {
189
if (isIterable(input)) {
190
const results = [];
191
for (const item of input) {
192
results.push(processItem(item));
193
}
194
return results;
195
}
196
197
throw new Error("Input must be iterable");
198
}
199
200
// Safe iteration
201
function safeForEach(collection: unknown, callback: (item: unknown) => void) {
202
if (isIterable(collection) && isFunction(callback)) {
203
for (const item of collection) {
204
callback(item);
205
}
206
}
207
}
208
```
209
210
## Combined Advanced Type Patterns
211
212
```typescript
213
import {
214
isFunction,
215
isPrimitive,
216
isIterable,
217
isOneOf,
218
isNull,
219
isUndefined
220
} from "is-what";
221
222
// Create nullish checker using factory function
223
const isNullOrUndefined = isOneOf(isNull, isUndefined);
224
225
function analyzeAdvancedType(value: unknown) {
226
if (isNullOrUndefined(value)) {
227
return `Nullish: ${value}`;
228
}
229
230
if (isPrimitive(value)) {
231
return `Primitive ${typeof value}: ${value}`;
232
}
233
234
if (isFunction(value)) {
235
return `Function: ${value.name || 'anonymous'} (${value.length} params)`;
236
}
237
238
if (isIterable(value)) {
239
const type = value.constructor?.name || "Iterable";
240
return `Iterable ${type}`;
241
}
242
243
return `Non-iterable object: ${value.constructor?.name || "Object"}`;
244
}
245
246
// Comprehensive data processor
247
function processAnyData(data: unknown) {
248
// Handle nullish values
249
if (isNullOrUndefined(data)) {
250
return { type: "nullish", value: data, processed: null };
251
}
252
253
// Handle primitives
254
if (isPrimitive(data)) {
255
return {
256
type: "primitive",
257
dataType: typeof data,
258
value: data,
259
processed: data
260
};
261
}
262
263
// Handle functions
264
if (isFunction(data)) {
265
return {
266
type: "function",
267
name: data.name || "anonymous",
268
paramCount: data.length,
269
processed: data.toString()
270
};
271
}
272
273
// Handle iterables
274
if (isIterable(data)) {
275
const items = Array.from(data);
276
return {
277
type: "iterable",
278
constructor: data.constructor?.name || "Iterable",
279
length: items.length,
280
processed: items
281
};
282
}
283
284
// Handle other objects
285
return {
286
type: "object",
287
constructor: data?.constructor?.name || "Object",
288
processed: data
289
};
290
}
291
292
// Type-safe utility functions
293
function createSafeMapper(mapperFn: unknown) {
294
if (!isFunction(mapperFn)) {
295
throw new Error("Mapper must be a function");
296
}
297
298
return (collection: unknown) => {
299
if (!isIterable(collection)) {
300
throw new Error("Collection must be iterable");
301
}
302
303
const results = [];
304
for (const item of collection) {
305
results.push(mapperFn(item));
306
}
307
return results;
308
};
309
}
310
311
function safeFunctionCall(fn: unknown, ...args: unknown[]) {
312
if (isFunction(fn)) {
313
try {
314
return { success: true, result: fn(...args) };
315
} catch (error) {
316
return { success: false, error };
317
}
318
}
319
320
return { success: false, error: "Not a function" };
321
}
322
323
// Example usage
324
analyzeAdvancedType(null); // "Nullish: null"
325
analyzeAdvancedType(42); // "Primitive number: 42"
326
analyzeAdvancedType(console.log); // "Function: log (1 params)"
327
analyzeAdvancedType([1, 2, 3]); // "Iterable Array"
328
analyzeAdvancedType({}); // "Non-iterable object: Object"
329
330
const result = processAnyData("hello world");
331
// Returns: {
332
// type: "primitive",
333
// dataType: "string",
334
// value: "hello world",
335
// processed: "hello world"
336
// }
337
338
const mapper = createSafeMapper((x: any) => x * 2);
339
const doubled = mapper([1, 2, 3]); // [2, 4, 6]
340
```
341
342
## Types
343
344
```typescript { .api }
345
type AnyFunction = (...args: any[]) => any;
346
type AnyAsyncFunction = (...args: unknown[]) => Promise<unknown>;
347
```