Skip to content

Commit e9f9adc

Browse files
authoredJul 11, 2024··
fix(spy): fix type error when assigning vi.spyOn to MockInstance of function overload (#6086)
1 parent fbed105 commit e9f9adc

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed
 

‎packages/spy/src/index.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -401,11 +401,11 @@ export function spyOn<T, G extends Properties<Required<T>>>(
401401
export function spyOn<T, M extends Classes<Required<T>> | Methods<Required<T>>>(
402402
obj: T,
403403
methodName: M
404-
): Required<T>[M] extends
405-
| { new (...args: infer A): infer R }
406-
| ((...args: infer A) => infer R)
404+
): Required<T>[M] extends { new (...args: infer A): infer R }
407405
? MockInstance<(this: R, ...args: A) => R>
408-
: never
406+
: T[M] extends Procedure
407+
? MockInstance<T[M]>
408+
: never
409409
export function spyOn<T, K extends keyof T>(
410410
obj: T,
411411
method: K,

‎test/core/test/vi.spec.ts

+35-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* @vitest-environment jsdom
33
*/
44

5-
import type { Mock, MockedFunction, MockedObject } from 'vitest'
5+
import type { Mock, MockInstance, MockedFunction, MockedObject } from 'vitest'
66
import { describe, expect, expectTypeOf, test, vi } from 'vitest'
77
import { getWorkerState } from '../../../packages/vitest/src/utils'
88

@@ -118,6 +118,40 @@ describe('testing vi utils', () => {
118118
expect(someFn4).not.toBeCalled()
119119
})
120120

121+
test(`vi.spyOn for function overload types`, () => {
122+
class MyElement {
123+
scrollTo(options?: ScrollToOptions): void
124+
scrollTo(x: number, y: number): void
125+
scrollTo() {}
126+
}
127+
128+
// verify `spyOn` is assignable to `MockInstance` with overload
129+
const spy: MockInstance<MyElement['scrollTo']> = vi.spyOn(
130+
MyElement.prototype,
131+
'scrollTo',
132+
)
133+
134+
// however `Parameters` only picks up the last overload
135+
// due to typescript limitation
136+
expectTypeOf(spy.mock.calls).toEqualTypeOf<
137+
[x: number, y: number][]
138+
>()
139+
})
140+
141+
test(`mock.contexts types`, () => {
142+
class TestClass {
143+
f(this: TestClass) {}
144+
g() {}
145+
}
146+
147+
const fSpy = vi.spyOn(TestClass.prototype, 'f')
148+
const gSpy = vi.spyOn(TestClass.prototype, 'g')
149+
150+
// contexts inferred only when `this` is explicitly annotated
151+
expectTypeOf(fSpy.mock.contexts).toEqualTypeOf<TestClass[]>()
152+
expectTypeOf(gSpy.mock.contexts).toEqualTypeOf<unknown[]>()
153+
})
154+
121155
test('can change config', () => {
122156
const state = getWorkerState()
123157
expect(state.config.hookTimeout).toBe(10000)

0 commit comments

Comments
 (0)
Please sign in to comment.