I'm confused how jest.fn() works in Typescript. For example
class MyClass {
myFunction() {
return 'hello'
}
}
let myClass = new MyClass()
myClass.myFunction = jest.fn()
From my understanding, myClass.myFunction has a type of '() => string' but jest.fn() returns a 'Mock'. I notice that 'Mock' is in fact extends 'Function' but Function is less specific then () => string so how could this work?
CodePudding user response:
Looking at the types from @types/jest
, it extends function but with a specific call signature:
interface Mock<T = any, Y extends any[] = any>
extends Function, MockInstance<T, Y> {
new (...args: Y): T;
(...args: Y): T; // <--
}
fn()
returns just Mock
and because the default return type (T
) is any
, this is allowed.
fn
can be called with type arguments to specify the return type explicitly or, more conveniently, the types can be inferred from the implementation function:
function fn<T, Y extends any[]>(implementation?: (...args: Y) => T): Mock<T, Y>;
Example:
// Identifies wrong return type (Type 'void' is not assignable to type 'string')
myClass.myFunction = jest.fn(() => { })
// Correct return type
myClass.myFunction = jest.fn(() => '')
If the types from the jest packages themselves are used, then jest.fn()
without anything else will also yield an error, because it returns a Mock<UnknownFunction>
.