0
# Function Types
1
2
Type utilities for function signatures, predicates, and function-related operations. These types help you work with function types in a type-safe manner.
3
4
## Capabilities
5
6
### AnyFunction
7
8
Matches function type with arguments type `Args` (`any[]` by default) and return type `ReturnType` (`any` by default).
9
10
```typescript { .api }
11
type AnyFunction<Args extends ReadonlyArray<any> = any[], ReturnType = any> =
12
(...args: Args) => ReturnType;
13
```
14
15
**Usage Example:**
16
17
```typescript
18
import type { AnyFunction } from "ts-essentials";
19
20
// Generic function type
21
type GenericHandler = AnyFunction; // (...args: any[]) => any
22
23
// Specific function signatures
24
type StringProcessor = AnyFunction<[string], string>; // (arg: string) => string
25
type NumberValidator = AnyFunction<[number], boolean>; // (arg: number) => boolean
26
type EventHandler = AnyFunction<[Event], void>; // (arg: Event) => void
27
28
// Higher-order function utilities
29
function createMiddleware<F extends AnyFunction>(
30
originalFn: F,
31
middleware: (args: Parameters<F>) => void
32
): F {
33
return ((...args: Parameters<F>) => {
34
middleware(args);
35
return originalFn(...args);
36
}) as F;
37
}
38
39
// Usage
40
const add: AnyFunction<[number, number], number> = (a, b) => a + b;
41
const loggedAdd = createMiddleware(add, ([a, b]) => {
42
console.log(`Adding ${a} + ${b}`);
43
});
44
```
45
46
### PredicateFunction
47
48
Matches type constraint for type guard, meaning first argument is used in return type and return type is type predicate.
49
50
```typescript { .api }
51
type PredicateFunction = <T, U extends T>(arg: T) => arg is U;
52
```
53
54
**Usage Example:**
55
56
```typescript
57
import type { PredicateFunction } from "ts-essentials";
58
59
// Type guard functions
60
const isString: PredicateFunction = (value: unknown): value is string => {
61
return typeof value === "string";
62
};
63
64
const isNumber: PredicateFunction = (value: unknown): value is number => {
65
return typeof value === "number";
66
};
67
68
// Generic predicate function factory
69
function createTypeGuard<T>(
70
checker: (value: unknown) => boolean
71
): PredicateFunction {
72
return (value: unknown): value is T => checker(value);
73
}
74
75
// Usage in filtering
76
const mixedArray: unknown[] = ["hello", 42, "world", true, 123];
77
const strings = mixedArray.filter(isString); // string[]
78
const numbers = mixedArray.filter(isNumber); // number[]
79
80
// Custom predicate functions
81
const isPositive: PredicateFunction = (value: number): value is number => {
82
return value > 0;
83
};
84
85
const positiveNumbers = [1, -2, 3, -4, 5].filter(isPositive); // number[]
86
```
87
88
### PredicateType
89
90
Constructs a type which equals to narrowed type in predicate function `Type`.
91
92
```typescript { .api }
93
type PredicateType<Type> = Type extends (arg: any) => arg is infer U ? U : never;
94
```
95
96
**Usage Example:**
97
98
```typescript
99
import type { PredicateType } from "ts-essentials";
100
101
// Extract the narrowed type from a predicate function
102
const isStringArray = (value: unknown): value is string[] => {
103
return Array.isArray(value) && value.every(item => typeof item === "string");
104
};
105
106
type StringArrayType = PredicateType<typeof isStringArray>; // string[]
107
108
// Use with other predicates
109
const isUser = (value: unknown): value is { id: number; name: string } => {
110
return typeof value === "object" &&
111
value !== null &&
112
"id" in value &&
113
"name" in value;
114
};
115
116
type UserType = PredicateType<typeof isUser>; // { id: number; name: string }
117
118
// Generic utility for working with predicate types
119
function processWithPredicate<P extends PredicateFunction>(
120
value: unknown,
121
predicate: P,
122
processor: (value: PredicateType<P>) => void
123
): void {
124
if (predicate(value)) {
125
processor(value); // Type is properly narrowed
126
}
127
}
128
129
// Usage
130
processWithPredicate(
131
someValue,
132
isUser,
133
(user) => {
134
console.log(user.id, user.name); // Type-safe access
135
}
136
);
137
```
138
139
## Advanced Usage
140
141
Combine function types for complex operations:
142
143
```typescript
144
import type { AnyFunction, PredicateFunction, PredicateType } from "ts-essentials";
145
146
// Function composition utilities
147
type ComposableFunction<T> = AnyFunction<[T], T>;
148
149
function compose<T>(...fns: ComposableFunction<T>[]): ComposableFunction<T> {
150
return (value: T) => fns.reduce((acc, fn) => fn(acc), value);
151
}
152
153
// Pipeline with type predicates
154
type Pipeline<T> = {
155
filter<U extends T>(predicate: (value: T) => value is U): Pipeline<U>;
156
map<U>(mapper: AnyFunction<[T], U>): Pipeline<U>;
157
collect(): T[];
158
};
159
160
function createPipeline<T>(items: T[]): Pipeline<T> {
161
return {
162
filter<U extends T>(predicate: (value: T) => value is U): Pipeline<U> {
163
return createPipeline(items.filter(predicate));
164
},
165
map<U>(mapper: AnyFunction<[T], U>): Pipeline<U> {
166
return createPipeline(items.map(mapper));
167
},
168
collect(): T[] {
169
return items;
170
}
171
};
172
}
173
174
// Usage
175
const data = [1, "hello", 2, "world", 3] as const;
176
const result = createPipeline(data)
177
.filter((x): x is string => typeof x === "string")
178
.map((s: string) => s.toUpperCase())
179
.collect(); // string[]
180
181
// Advanced predicate combinations
182
type CombinedPredicate<T, U, V> = (
183
value: T
184
) => value is U & V;
185
186
function createCombinedPredicate<T, U, V>(
187
predicate1: (value: T) => value is U,
188
predicate2: (value: T) => value is V
189
): CombinedPredicate<T, U, V> {
190
return (value: T): value is U & V => {
191
return predicate1(value) && predicate2(value);
192
};
193
}
194
195
// Function signature validation
196
type ValidateFunction<F extends AnyFunction> = {
197
argCount: Parameters<F>['length'];
198
returnType: ReturnType<F>;
199
isValid: boolean;
200
};
201
202
function validateFunction<F extends AnyFunction>(
203
fn: F,
204
expectedArgCount: number
205
): ValidateFunction<F> {
206
return {
207
argCount: fn.length as Parameters<F>['length'],
208
returnType: undefined as ReturnType<F>, // Conceptual
209
isValid: fn.length === expectedArgCount
210
};
211
}
212
```
213
214
## Types
215
216
```typescript { .api }
217
type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
218
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
219
```