0
# Type System
1
2
Comprehensive TypeScript utilities for type-safe mocking with generic preservation and utility functions for working with mocked objects.
3
4
## Capabilities
5
6
### Type Assertion Utility
7
8
Provides type assertion for objects that have been mocked, enabling full type safety in test code.
9
10
```typescript { .api }
11
/**
12
* Type assertion utility for mocked objects
13
* @param source - Object to assert as mocked
14
* @param options - Mocking depth options
15
* @returns Type-asserted mocked object
16
*/
17
function mocked<T extends object>(source: T, options?: {shallow: false}): Mocked<T>;
18
function mocked<T extends object>(source: T, options: {shallow: true}): MockedShallow<T>;
19
function mocked<T extends object>(source: T, _options?: {shallow: boolean}): Mocked<T> | MockedShallow<T>;
20
```
21
22
**Usage Examples:**
23
24
```typescript
25
import { mocked, spyOn } from "jest-mock";
26
27
class UserService {
28
async getUser(id: string) { return { id, name: 'User' }; }
29
async saveUser(user: any) { return user; }
30
}
31
32
const userService = new UserService();
33
34
// Spy on methods
35
spyOn(userService, 'getUser');
36
spyOn(userService, 'saveUser');
37
38
// Type assertion for full type safety
39
const mockedUserService = mocked(userService);
40
mockedUserService.getUser.mockResolvedValue({ id: '1', name: 'Test User' });
41
mockedUserService.saveUser.mockResolvedValue({ id: '2', name: 'Saved User' });
42
43
// Now TypeScript knows these are mock functions
44
console.log(mockedUserService.getUser.mock.calls); // Type-safe access
45
```
46
47
### Mocked Type Wrappers
48
49
Type definitions that transform regular types into their mocked equivalents while preserving the original type structure.
50
51
```typescript { .api }
52
/**
53
* Deep mocked type that recursively mocks all properties
54
*/
55
type Mocked<T> = T extends ClassLike
56
? MockedClass<T>
57
: T extends FunctionLike
58
? MockedFunction<T>
59
: T extends object
60
? MockedObject<T>
61
: T;
62
63
/**
64
* Shallow mocked type that only mocks top-level properties
65
*/
66
type MockedShallow<T> = T extends ClassLike
67
? MockedClass<T>
68
: T extends FunctionLike
69
? MockedFunctionShallow<T>
70
: T extends object
71
? MockedObjectShallow<T>
72
: T;
73
74
/**
75
* Mocked class type preserving constructor signature
76
*/
77
type MockedClass<T extends ClassLike> = MockInstance<
78
(...args: ConstructorParameters<T>) => Mocked<InstanceType<T>>
79
> & MockedObject<T>;
80
81
/**
82
* Mocked function type preserving function signature
83
*/
84
type MockedFunction<T extends FunctionLike> = MockInstance<T> & MockedObject<T>;
85
86
/**
87
* Deep mocked object type
88
*/
89
type MockedObject<T extends object> = {
90
[K in keyof T]: T[K] extends ClassLike
91
? MockedClass<T[K]>
92
: T[K] extends FunctionLike
93
? MockedFunction<T[K]>
94
: T[K] extends object
95
? MockedObject<T[K]>
96
: T[K];
97
} & T;
98
99
/**
100
* Shallow mocked object type
101
*/
102
type MockedObjectShallow<T extends object> = {
103
[K in keyof T]: T[K] extends ClassLike
104
? MockedClass<T[K]>
105
: T[K] extends FunctionLike
106
? MockedFunctionShallow<T[K]>
107
: T[K];
108
} & T;
109
110
type MockedFunctionShallow<T extends FunctionLike> = MockInstance<T> & T;
111
112
type ClassLike = new (...args: any) => any;
113
type FunctionLike = (...args: any) => any;
114
```
115
116
**Usage Examples:**
117
118
```typescript
119
import { MockedFunction, MockedClass, Mocked } from "jest-mock";
120
121
// Function mocking
122
type MyFunction = (x: number) => string;
123
type MockedMyFunction = MockedFunction<MyFunction>;
124
// MockedMyFunction has both MockInstance methods and original function properties
125
126
// Class mocking
127
class ApiClient {
128
baseUrl: string;
129
constructor(baseUrl: string) { this.baseUrl = baseUrl; }
130
async get(path: string) { return {}; }
131
}
132
133
type MockedApiClient = MockedClass<typeof ApiClient>;
134
// MockedApiClient constructor returns Mocked<ApiClient> instance
135
136
// Object mocking
137
interface Config {
138
database: {
139
host: string;
140
connect(): Promise<void>;
141
};
142
cache: {
143
set(key: string, value: any): void;
144
get(key: string): any;
145
};
146
}
147
148
type MockedConfig = Mocked<Config>;
149
// All nested functions become MockedFunction<T>
150
// All nested objects become MockedObject<T>
151
```
152
153
### Utility Key Types
154
155
Helper types for categorizing object properties by their characteristics.
156
157
```typescript { .api }
158
/**
159
* Keys that are constructors (class-like functions)
160
*/
161
type ConstructorLikeKeys<T> = keyof {
162
[K in keyof T as Required<T>[K] extends ClassLike ? K : never]: T[K];
163
};
164
165
/**
166
* Keys that are methods (function-like properties)
167
*/
168
type MethodLikeKeys<T> = keyof {
169
[K in keyof T as Required<T>[K] extends FunctionLike ? K : never]: T[K];
170
};
171
172
/**
173
* Keys that are properties (non-method, non-constructor)
174
*/
175
type PropertyLikeKeys<T> = Exclude<keyof T, ConstructorLikeKeys<T> | MethodLikeKeys<T>>;
176
```
177
178
**Usage Examples:**
179
180
```typescript
181
interface MyObject {
182
name: string; // PropertyLikeKeys
183
count: number; // PropertyLikeKeys
184
method(): void; // MethodLikeKeys
185
Constructor: new () => any; // ConstructorLikeKeys
186
}
187
188
type Methods = MethodLikeKeys<MyObject>; // 'method'
189
type Properties = PropertyLikeKeys<MyObject>; // 'name' | 'count'
190
type Ctors = ConstructorLikeKeys<MyObject>; // 'Constructor'
191
```
192
193
### Spy Type Definitions
194
195
Specialized types for spy operations that preserve original signatures while adding mock capabilities.
196
197
```typescript { .api }
198
/**
199
* Generic spied type
200
*/
201
type Spied<T extends ClassLike | FunctionLike> = T extends ClassLike
202
? SpiedClass<T>
203
: T extends FunctionLike
204
? SpiedFunction<T>
205
: never;
206
207
/**
208
* Spied class constructor
209
*/
210
type SpiedClass<T extends ClassLike = UnknownClass> = MockInstance<
211
(...args: ConstructorParameters<T>) => InstanceType<T>
212
>;
213
214
/**
215
* Spied function
216
*/
217
type SpiedFunction<T extends FunctionLike = UnknownFunction> = MockInstance<
218
(...args: Parameters<T>) => ReturnType<T>
219
>;
220
221
/**
222
* Spied property getter
223
*/
224
type SpiedGetter<T> = MockInstance<() => T>;
225
226
/**
227
* Spied property setter
228
*/
229
type SpiedSetter<T> = MockInstance<(arg: T) => void>;
230
231
type UnknownFunction = (...args: Array<unknown>) => unknown;
232
type UnknownClass = new (...args: Array<unknown>) => unknown;
233
```
234
235
**Usage Examples:**
236
237
```typescript
238
import { spyOn, SpiedFunction, SpiedClass } from "jest-mock";
239
240
function myFunction(x: number): string { return x.toString(); }
241
class MyClass { constructor(public value: string) {} }
242
243
// Spied function maintains original signature
244
const spiedFn: SpiedFunction<typeof myFunction> = spyOn(obj, 'myFunction');
245
spiedFn.mockReturnValue('mocked');
246
247
// Spied class constructor
248
const SpiedConstructor: SpiedClass<typeof MyClass> = spyOn(MyClass.prototype, 'constructor');
249
```
250
251
## Advanced Type Usage
252
253
### Complex Mocking Scenarios
254
255
```typescript
256
import { Mocked, MockedShallow } from "jest-mock";
257
258
// Deep mocking - all nested properties become mocked
259
interface NestedService {
260
database: {
261
users: {
262
find(id: string): Promise<User>;
263
save(user: User): Promise<void>;
264
};
265
posts: {
266
findByUser(userId: string): Promise<Post[]>;
267
};
268
};
269
}
270
271
type DeepMocked = Mocked<NestedService>;
272
// database.users.find becomes MockedFunction
273
// database.posts.findByUser becomes MockedFunction
274
275
// Shallow mocking - only top-level properties mocked
276
type ShallowMocked = MockedShallow<NestedService>;
277
// database property is mocked, but database.users.find is not
278
```
279
280
### Generic Type Preservation
281
282
```typescript
283
import { MockedFunction } from "jest-mock";
284
285
// Generic functions maintain their generic nature when mocked
286
function genericFunction<T>(input: T): Promise<T[]> {
287
return Promise.resolve([input]);
288
}
289
290
type MockedGeneric = MockedFunction<typeof genericFunction>;
291
// Still maintains <T>(input: T) => Promise<T[]> signature
292
// Plus MockInstance methods for control
293
```
294
295
### Conditional Type Usage
296
297
```typescript
298
// Utility type to check if something is mockable
299
type IsMockable<T> = T extends ClassLike | FunctionLike ? true : false;
300
301
type CanMockString = IsMockable<string>; // false
302
type CanMockFunction = IsMockable<() => void>; // true
303
type CanMockClass = IsMockable<new () => any>; // true
304
```
305
306
## Types Reference
307
308
```typescript { .api }
309
interface MockInstance<T extends FunctionLike = UnknownFunction> extends Disposable {
310
_isMockFunction: true;
311
_protoImpl: Function;
312
mock: MockFunctionState<T>;
313
getMockImplementation(): T | undefined;
314
getMockName(): string;
315
mockClear(): this;
316
mockReset(): this;
317
mockRestore(): void;
318
mockImplementation(fn: T): this;
319
mockImplementationOnce(fn: T): this;
320
withImplementation(fn: T, callback: () => Promise<unknown>): Promise<void>;
321
withImplementation(fn: T, callback: () => void): void;
322
mockName(name: string): this;
323
mockReturnThis(): this;
324
mockReturnValue(value: ReturnType<T>): this;
325
mockReturnValueOnce(value: ReturnType<T>): this;
326
mockResolvedValue(value: ResolveType<T>): this;
327
mockResolvedValueOnce(value: ResolveType<T>): this;
328
mockRejectedValue(value: RejectType<T>): this;
329
mockRejectedValueOnce(value: RejectType<T>): this;
330
}
331
```