Extending third party module that is globally exposed

A simple way is:

customMatchers.ts

declare global {
    namespace jest {
        interface Matchers<R> {
            // add any of your custom matchers here
            toBeDivisibleBy: (argument: number) => {};
        }
    }
}

// this will extend the expect with a custom matcher
expect.extend({
    toBeDivisibleBy(received: number, argument: number) {
        const pass = received % argument === 0;
        if (pass) {
            return {
                message: () => `expected ${received} not to be divisible by ${argument}`,
                pass: true
            };
        } else {
            return {
                message: () => `expected ${received} to be divisible by ${argument}`,
                pass: false
            };
        }
    }
});

my.spec.ts

import "path/to/customMatchers";

test('even and odd numbers', () => {
   expect(100).toBeDivisibleBy(2);
   expect(101).not.toBeDivisibleBy(2);
});

OK, so there are 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 file

myMatcher.ts

// use declare global within a module to introduce or augment a global declaration.
declare global {
  namespace jest {
    interface Matchers {
      myMatcher: typeof myMatcher;
    }
  }
}
export default function myMatcher<T>(this: jest.MatcherUtils, received: T, expected: T) {
  const pass = received === expected;
  return {
    pass,
    message: () => `expected ${pass ? '!' : '='}==`
  };
}

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

// ensure this is parsed as a module.
export {};

declare global {
  namespace jest {
    interface Matchers {
      myMatcher: typeof myMatcher;
    }
  }
}
function myMatcher<T>(this: jest.MatcherUtils, received: T, expected: T) {
  const pass = received === expected;
  return {
    pass,
    message: () => `expected ${pass ? '!' : '='}==`
  };
}

expect.extend({
  myMatcher
});

someTest.ts

import './myMatcher';

it('should work', () => {
  expect('str').myMatcher('str');
});

Answer by @AluanHaddad is almost correct, sans a few types. This one works:

export {};

declare global {
  namespace jest {
    interface Matchers<R> {
      myMatcher: (received: string) => R;
    }
  }
}

function myMatcher<T>(this: jest.MatcherUtils, received: string, expected: string): jest.CustomMatcherResult {
  const pass = received === expected;
  return {
    pass,
    message: (): string => `expected ${received} to be ${expected}`,
  }
}

expect.extend({
  myMatcher,
});

For a real-world example, see https://github.com/Quantum-Game/quantum-tensors/blob/master/tests/customMatchers.ts (and that the tests actually pass: https://travis-ci.com/Quantum-Game/quantum-tensors).