0
# Testing Module
1
2
Built-in type testing utilities for validating type transformations and ensuring type correctness in ts-toolbelt operations.
3
4
## Capabilities
5
6
### Test Result Types
7
8
Basic types representing test outcomes.
9
10
```typescript { .api }
11
/**
12
* Represents a passing test (true condition)
13
*/
14
type Pass = 1;
15
16
/**
17
* Represents a failing test (false condition)
18
*/
19
type Fail = 0;
20
```
21
22
**Usage Examples:**
23
24
```typescript
25
import { Test } from "ts-toolbelt";
26
27
// Basic usage
28
type PassingTest = Test.Pass; // 1
29
type FailingTest = Test.Fail; // 0
30
31
// Conditional results
32
type TestResult<T> = T extends string ? Test.Pass : Test.Fail;
33
type StringTest = TestResult<string>; // 1 (Pass)
34
type NumberTest = TestResult<number>; // 0 (Fail)
35
```
36
37
### Type Checking Function
38
39
Validate that types match expected results.
40
41
```typescript { .api }
42
/**
43
* Check if a type matches expected result with specified outcome
44
* @param Type - Actual type to test
45
* @param Expect - Expected type
46
* @param Outcome - Expected test outcome (Pass or Fail)
47
* @returns Type-level validation of the test
48
*/
49
declare function check<Type, Expect, Outcome extends Boolean>(
50
debug?: Equals<Equals<Type, Expect>, Outcome>
51
): Equals<Equals<Type, Expect>, Outcome>;
52
```
53
54
**Usage Examples:**
55
56
```typescript
57
import { Test, A, O, L } from "ts-toolbelt";
58
59
// Test type equality
60
Test.check<string, string, Test.Pass>(); // ✓ Pass - types match
61
Test.check<string, number, Test.Fail>(); // ✓ Pass - correctly expects failure
62
// Test.check<string, number, Test.Pass>(); // ✗ Compile error - test would fail
63
64
// Test ts-toolbelt operations
65
Test.check<
66
O.Pick<{ a: string; b: number; c: boolean }, "a" | "b">,
67
{ a: string; b: number },
68
Test.Pass
69
>(); // ✓ Pick operation works correctly
70
71
Test.check<
72
L.Head<[1, 2, 3]>,
73
1,
74
Test.Pass
75
>(); // ✓ Head operation works correctly
76
77
Test.check<
78
A.Equals<"hello", "hello">,
79
1,
80
Test.Pass
81
>(); // ✓ Equals operation works correctly
82
83
// Test complex transformations
84
type User = { name: string; age: number; email?: string };
85
type RequiredUser = O.Required<User>;
86
87
Test.check<
88
RequiredUser,
89
{ name: string; age: number; email: string },
90
Test.Pass
91
>(); // ✓ Required transformation works
92
93
// Test negative cases
94
Test.check<
95
O.Pick<User, "nonexistent">,
96
{},
97
Test.Pass
98
>(); // This would actually fail compilation due to invalid key
99
```
100
101
### Batch Testing
102
103
Run multiple tests together for comprehensive validation.
104
105
```typescript { .api }
106
/**
107
* Run multiple type tests in batch
108
* @param checks - Array of test results (must all be Pass/1)
109
* @returns void if all tests pass
110
*/
111
declare function checks(checks: 1[]): void;
112
```
113
114
**Usage Examples:**
115
116
```typescript
117
import { Test, O, L, S, N } from "ts-toolbelt";
118
119
// Batch test multiple operations
120
Test.checks([
121
// Object operations
122
Test.check<O.Keys<{ a: 1; b: 2 }>, "a" | "b", Test.Pass>(),
123
Test.check<O.Values<{ a: 1; b: 2 }>, 1 | 2, Test.Pass>(),
124
Test.check<O.At<{ a: string }, "a">, string, Test.Pass>(),
125
126
// List operations
127
Test.check<L.Length<[1, 2, 3]>, 3, Test.Pass>(),
128
Test.check<L.Head<["a", "b"]>, "a", Test.Pass>(),
129
Test.check<L.Tail<[1, 2, 3]>, [2, 3], Test.Pass>(),
130
131
// String operations
132
Test.check<S.Length<"hello">, 5, Test.Pass>(),
133
Test.check<S.Split<"a,b,c", ",">, ["a", "b", "c"], Test.Pass>(),
134
135
// Number operations
136
Test.check<N.Add<2, 3>, 5, Test.Pass>(),
137
Test.check<N.Greater<5, 3>, 1, Test.Pass>(),
138
]);
139
140
// Test suite for specific functionality
141
const testObjectMerge = Test.checks([
142
Test.check<
143
O.Merge<{ a: 1 }, { b: 2 }>,
144
{ a: 1; b: 2 },
145
Test.Pass
146
>(),
147
Test.check<
148
O.Merge<{ a: 1; b: 2 }, { b: 3; c: 4 }>,
149
{ a: 1; b: 3; c: 4 },
150
Test.Pass
151
>(),
152
Test.check<
153
O.Merge<{}, { a: 1 }>,
154
{ a: 1 },
155
Test.Pass
156
>(),
157
]);
158
159
// Test suite for list transformations
160
const testListOperations = Test.checks([
161
Test.check<L.Append<[1, 2], 3>, [1, 2, 3], Test.Pass>(),
162
Test.check<L.Prepend<[2, 3], 1>, [1, 2, 3], Test.Pass>(),
163
Test.check<L.Reverse<[1, 2, 3]>, [3, 2, 1], Test.Pass>(),
164
Test.check<L.Concat<[1, 2], [3, 4]>, [1, 2, 3, 4], Test.Pass>(),
165
]);
166
```
167
168
### Advanced Testing Patterns
169
170
Complex testing scenarios for comprehensive validation.
171
172
**Usage Examples:**
173
174
```typescript
175
import { Test, O, L, F, A } from "ts-toolbelt";
176
177
// Test generic type functions
178
type TestGeneric<T> = Test.check<
179
O.Pick<{ a: T; b: number }, "a">,
180
{ a: T },
181
Test.Pass
182
>;
183
184
type StringGenericTest = TestGeneric<string>; // ✓
185
type NumberGenericTest = TestGeneric<number>; // ✓
186
187
// Test conditional logic
188
type TestConditional<T> = T extends string
189
? Test.check<T, string, Test.Pass>
190
: Test.check<T, string, Test.Fail>;
191
192
type ConditionalStringTest = TestConditional<"hello">; // ✓
193
type ConditionalNumberTest = TestConditional<42>; // ✓
194
195
// Test complex transformations
196
type DeepObject = {
197
user: {
198
profile: {
199
name: string;
200
details: {
201
age: number;
202
};
203
};
204
};
205
};
206
207
const testDeepOperations = Test.checks([
208
Test.check<
209
O.At<DeepObject, "user">,
210
{ profile: { name: string; details: { age: number } } },
211
Test.Pass
212
>(),
213
Test.check<
214
A.Keys<DeepObject>,
215
"user",
216
Test.Pass
217
>(),
218
]);
219
220
// Test error cases (negative testing)
221
const testErrorCases = Test.checks([
222
// These should explicitly test for failure
223
Test.check<string, number, Test.Fail>(), // Different types
224
Test.check<{ a: 1 }, { a: 2 }, Test.Fail>(), // Different values
225
Test.check<[1, 2], [1, 2, 3], Test.Fail>(), // Different lengths
226
]);
227
228
// Test edge cases
229
const testEdgeCases = Test.checks([
230
// Empty types
231
Test.check<L.Length<[]>, 0, Test.Pass>(),
232
Test.check<O.Keys<{}>, never, Test.Pass>(),
233
Test.check<S.Length<"">, 0, Test.Pass>(),
234
235
// Never and unknown
236
Test.check<A.Equals<never, never>, 1, Test.Pass>(),
237
Test.check<A.Extends<never, any>, 1, Test.Pass>(),
238
239
// Union handling
240
Test.check<A.Keys<{ a: 1 } | { b: 2 }>, "a" | "b", Test.Pass>(),
241
]);
242
243
// Performance testing (ensuring operations complete)
244
const testPerformance = Test.checks([
245
// Large unions
246
Test.check<
247
A.Contains<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10, 5>,
248
1,
249
Test.Pass
250
>(),
251
252
// Deep nesting
253
Test.check<
254
L.Length<[1, [2, [3, [4, [5]]]]]>,
255
2, // Only counts top level
256
Test.Pass
257
>(),
258
]);
259
260
// Regression tests
261
const testRegressions = Test.checks([
262
// Previous bug fixes
263
Test.check<O.Merge<{ a?: 1 }, { a: 2 }>, { a: 2 }, Test.Pass>(),
264
Test.check<L.At<[1, 2, 3], 1>, 2, Test.Pass>(),
265
Test.check<S.Replace<"hello", "l", "x">, "hexxo", Test.Pass>(),
266
]);
267
```
268
269
### Testing Best Practices
270
271
Guidelines for effective type testing with ts-toolbelt.
272
273
**Usage Examples:**
274
275
```typescript
276
import { Test } from "ts-toolbelt";
277
278
// 1. Test both positive and negative cases
279
const comprehensiveTest = Test.checks([
280
// Positive: what should work
281
Test.check<string, string, Test.Pass>(),
282
Test.check<1 | 2, number, Test.Fail>(), // Union doesn't extend specific type
283
284
// Negative: what should fail
285
Test.check<string, number, Test.Fail>(),
286
Test.check<{ a: 1; b: 2 }, { a: 1 }, Test.Fail>(), // Extra properties
287
]);
288
289
// 2. Test boundary conditions
290
const boundaryTest = Test.checks([
291
Test.check<[], never[], Test.Fail>(), // Empty array vs never array
292
Test.check<{}, Record<string, never>, Test.Fail>(), // Empty object variations
293
Test.check<unknown, any, Test.Fail>(), // Unknown vs any
294
]);
295
296
// 3. Test with realistic data structures
297
type ApiResponse<T> = {
298
success: boolean;
299
data: T;
300
meta: {
301
timestamp: number;
302
version: string;
303
};
304
};
305
306
const realWorldTest = Test.checks([
307
Test.check<
308
O.Pick<ApiResponse<string>, "success" | "data">,
309
{ success: boolean; data: string },
310
Test.Pass
311
>(),
312
Test.check<
313
O.At<ApiResponse<number>, "meta">,
314
{ timestamp: number; version: string },
315
Test.Pass
316
>(),
317
]);
318
319
// 4. Document test intent with descriptive names
320
type TestUserPermissions = Test.checks([
321
Test.check<
322
O.Has<{ read: true; write: false }, "admin">,
323
0, // Should not have admin permission
324
Test.Pass
325
>(),
326
Test.check<
327
O.Required<{ read?: boolean; write?: boolean }>,
328
{ read: boolean; write: boolean },
329
Test.Pass
330
>(),
331
]);
332
```
333
334
## Types
335
336
```typescript { .api }
337
// Test result types
338
type Pass = 1;
339
type Fail = 0;
340
type Boolean = 0 | 1;
341
342
// Internal equality checking (used by check function)
343
type Equals<A1, A2> = (<A>() => A extends A1 ? 1 : 0) extends (<A>() => A extends A2 ? 1 : 0) ? 1 : 0;
344
```