笑话 TypeScript 类“没有重载需要 1 个类型参数”

Posted

技术标签:

【中文标题】笑话 TypeScript 类“没有重载需要 1 个类型参数”【英文标题】:Jest mocking TypeScript class "No overload expects 1 type arguments" 【发布时间】:2019-07-23 06:45:49 【问题描述】:

我正在尝试使用 Jest 模拟 TypeScript 类,我显然正在做某事,因为收到以下错误:

error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments.

这是我的代码:

Foo.ts

export default class Foo 
  bar(): number 
    return Math.random()
  

Foo.test.ts

import Foo from './Foo'

describe('Foo', () => 
  it("should pass", () => 
    const MockFoo = jest.fn<Foo>(() => (
      bar: jest.fn(() => 
        return 123
      ),
    ))
  )
)

完整的错误:

TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
src/Foo.test.ts:6:29 - error TS2743: No overload expects 1 type arguments, but overloads do exist that expect either 0 or 2 type arguments.

6     const MockFoo = jest.fn<Foo>(() => (
                              ~~~

更新

如果有任何相关性,这是我的 Jest 配置:

module.exports = 
  moduleFileExtensions: ['ts', 'js'],
  transform: 
    '^.+\\.ts$': 'ts-jest',
  ,
  testMatch: ['**/src/**/*.test.(ts)'],
  testEnvironment: 'node',
;

【问题讨论】:

【参考方案1】:

事实证明,通过关闭诊断 [1],可以让 TypeScript 编译器忽略此类错误。

// jest.config.js
module.exports = 
  // [...]
  globals: 
    'ts-jest': 
      diagnostics: false
    
  
;

但是,我目前还不清楚这可能会产生什么其他影响。

[1]https://huafu.github.io/ts-jest/user/config/diagnostics#enabling-diagnostics-for-test-files-only

【讨论】:

【参考方案2】:

Jest 具有以下 jest.fn 的签名:

/**
 * Creates a mock function. Optionally takes a mock implementation.
 */
function fn<T, Y extends any[]>(implementation?: (...args: Y) => T): Mock<T, Y>;

因此,您需要为 args 指定类型数组,在您的特定情况下,您可以只传递一个空数组,因为您的实现函数中没有 args。

const MockFoo = jest.fn<Foo, []>(() => (

【讨论】:

【参考方案3】:

你可以使用ts-jest的mocked()函数:

这是所有类型安全的,并且在 TypeScript 中编译时不会出现警告:

import Foo from './Foo'
import mocked from 'ts-jest/utils'

function argIsFoo(foo : Foo) 
    ; // do nothing


describe('Foo', () => 
    it("should pass", () => 
        const mockFoo = mocked(
            bar: jest.fn(() => 
                return 123
            )
        );

        // mockFoo is compatible with Foo class
        argIsFoo(mockFoo);

        // method has the right type
        expect(mockFoo.bar()).toEqual(123);

        // can use the mock in expectations
        expect(mockFoo.bar).toHaveBeenCalled();

        // is type safe access method as a mock
        expect(mockFoo.bar.mock.calls.length).toEqual(1);
    );
);

如果你只想模拟出 Foo 的一些方法,那么在mocked() 中你需要用as unknown as Foo 强制转换你的模拟对象

import mocked from 'ts-jest/utils'

class Foo 
    bar(): number 
        return Math.random();
    
    dontMockMe(): string 
        return "buzz";
    


function argIsFoo(foo : Foo) 
    ; // do nothing


describe('Foo', () => 
    it("should pass", () => 
        const mockFoo = mocked(
            bar: jest.fn(() => 
                return 123
            )
         as unknown as Foo);

        // mockFoo is compatible with Foo class
        argIsFoo(mockFoo);

        // method has the right type
        expect(mockFoo.bar()).toEqual(123);

        // can use the mock in expectations
        expect(mockFoo.bar).toHaveBeenCalled();

        // is type safe access method as a mock
        expect(mockFoo.bar.mock.calls.length).toEqual(1);
    );
);

【讨论】:

以上是关于笑话 TypeScript 类“没有重载需要 1 个类型参数”的主要内容,如果未能解决你的问题,请参考以下文章

在笑话和打字稿中模拟交叉点观察者

笑话:await vs setImmediate vs useFakeTimers vs new Promise(setImmediate)

笑话:如何模拟一个类的一个特定方法

顺风复杂类(焦点等)和苗条项目中的笑话出错。仅在运行测试时

格式化 DateTime 错误“方法 'ToString' 没有重载需要 1 个参数”

方法“ToString”没有重载需要 1 个参数