I am trying to add a custom matcher to Jest in Typescript. This works fine, but I can't get Typescript to recognize the extended Matchers
.
myMatcher.ts
export default function myMatcher (this: jest.MatcherUtils, received: any, expected: any): { pass: boolean; message (): string; } {
const pass = received === expected;
return {
pass: pass,
message: () => `expected ${pass ? '!' : '='}==`,
}
}
myMatcher.d.ts
declare namespace jest {
interface Matchers {
myMatcher (expected: any): boolean;
}
}
someTest.ts
import myMatcher from './myMatcher';
expect.extend({
myMatcher,
})
it('should work', () => {
expect('str').myMatcher('str');
})
tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"moduleResolution": "node",
"module": "es6",
"target": "es5",
"lib": [
"es7",
"dom"
]
},
"types": [
"jest"
],
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"dist",
"doc",
"**/__mocks__/*",
"**/__tests__/*"
]
}
In someTests.ts, I get the error
error TS2339: Property 'myMatcher' does not exist on type 'Matchers'
I have read through the Microsoft documentation several times, but I can't figure out how to do the namespace merging with globally available types (not exported).
Putting it in the index.d.ts from jest works fine, but isn't a good solution for a rapidly changing codebase and classes being extended by multiple parties.
OK, so a few issues here
When a source file (
.ts
or.tsx
) file and a declaration file (.d.ts
) file are both candidates for module resolution, as is the case here, the compiler will resolve the source file.You probably have two files because you want to export a value and also modify the type of the global object
jest
. However, you do not need two files for this as TypeScript has a specific construct for augmenting the global scope from within a module. That is to say, all you need is the following.ts
filemyMatcher.ts
That said, if you have such a situation, it is a good practice to perform the global mutation and the global type augmentation in the same file. Given that, I would consider rewriting it as follows
myMatcher.ts
someTest.ts
A simple way is:
customMatchers.ts
my.spec.ts