为什么 jest.fn() 可以分配给 Typescript 中的任何函数?

Why jest.fn() can be assigned to any function in Typescript?

我对 jest.fn() 在 Typescript 中的工作方式感到困惑。例如

class MyClass {
  myFunction() {
    return 'hello'
  }
}

let myClass = new MyClass()
myClass.myFunction = jest.fn()

据我了解,myClass.myFunction 的类型为“() => string”,但 jest.fn() returns 为 'Mock'。我注意到 'Mock' 实际上是 extends 'Function' 但 Function 没有那么具体 () => string 那么这怎么能工作呢?

查看the types from @types/jest,它扩展了功能但具有特定的调用签名:

interface Mock<T = any, Y extends any[] = any>
  extends Function, MockInstance<T, Y> {
    new (...args: Y): T;
    (...args: Y): T; // <--
}

fn() return 只是 Mock,因为默认的 return 类型 (T) 是 any,这是允许的。

可以使用类型参数调用

fn 以显式指定 return 类型,或者更方便的是,可以从实现函数中推断类型:

function fn<T, Y extends any[]>(implementation?: (...args: Y) => T): Mock<T, Y>;

示例:

// Identifies wrong return type (Type 'void' is not assignable to type 'string')
myClass.myFunction = jest.fn(() => { })

// Correct return type
myClass.myFunction = jest.fn(() => '')

Playground


如果使用 jest 包本身的类型,那么 jest.fn() 没有任何其他内容也会产生错误,因为它 return 是 Mock<UnknownFunction>.

Playground