如何让 TypeScript 知道自定义 Jest 匹配器?
Posted
技术标签:
【中文标题】如何让 TypeScript 知道自定义 Jest 匹配器?【英文标题】:How to let TypeScript know about custom Jest matchers? 【发布时间】:2020-04-17 02:10:38 【问题描述】:我有一个使用 jest 的 react/typescript 项目,其中我有一个自定义匹配器,例如:
export const MyCustomMatchers =
toBeTheSameAsRemote: function(_util: any, _customEqualityTesters: any)
return
compare: function(actual: Brand, expected: RemoteBrand)
const pass: boolean = attributesMatch(actual, expected);
const message: string = pass
? 'Local matches Remote'
: 'Local does not match Remote';
return pass, message: () => message ;
;
;
我在测试中通过在 describe
函数中引用它:
beforeEach(() =>
jasmine.addMatchers(MyCustomMatchers);
);
并在it
函数中像这样使用:
expect(localValue).toBeTheSameAsRemote(remoteValue);
测试运行正常,但 typescript 编译器无法识别匹配器,这是有道理的,因为我没有在类型系统的任何地方定义它
Property 'toBeTheSameAsRemote' does not exist on type 'JestMatchersShape<Matchers<void, MyType[]>, Matchers<Promise<void>, MyType[]>>'.ts(2339)
到目前为止,我发现与扩展 jasmine 和/或 jest 的命名空间有关,例如
declare namespace jasmine
interface Matchers
toBeTheSameAsRemote(remote: any): any;
这对我没有用。
你有什么想法吗?
【问题讨论】:
【参考方案1】:试试这个:
以下文件声明了实际的
实现 expect.extend
以及 TypeScript 声明。
custom-matcher.ts
:
declare global
namespace jest
interface Matchers<R>
toBeTheSameAsRemote: (expected: string) => CustomMatcherResult;
expect.extend(
/**
* Notice that this implementation has 2 arguments, but the implementation inside the Matchers only has 1
*/
toBeTheSameAsRemote(
received: string,
expected: string
)
return
pass: false,
message: "A GraphQl error was expected"
;
);
// I am exporting nothing just so we can import this file
export default undefined;
现在,在您的测试文件中,导入上述模块。
actual-test.ts
:
// importing the custom matcher file is important
import "../../testing/custom-matchers/custom-matcher";
describe("something", () =>
it("should work", () =>
expect(localValue).toBeTheSameAsRemote(remoteValue);
);
);
注意事项:
expect.extend
将从导入中自动调用。无需对每个测试文件都调用expect.extend
。
declare global
是必需的,因为 jest
没有显式导入(它是全局导入)。
toBeTheSameAsRemote
函数的签名在 expect.extend
内部和 TypeScript 上不同。
【讨论】:
在 Typescript v4 中 @typescript-eslint/no-namespace 失败并显示ES2015 module syntax is preferred over custom TypeScript modules and namespaces
。有没有比简单地禁用此规则更好的方法?或者只要jest
是全局的,就必须禁用?
ESLint:ES2015 模块语法优于自定义 TypeScript 模块和命名空间。(@typescript-eslint/no-namespace)以上是关于如何让 TypeScript 知道自定义 Jest 匹配器?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Jest 的自定义测试环境文件中使用 TypeScript?
调度自定义事件并测试它是不是被正确触发(React TypeScript,Jest)