I have an issue with jest not recognizing merged interfaces correctly.
I have a decleration file from a @types/ library install with npm.
The implementation is implemented by the environment as a global in the production system and I have no access to it (think window
as browser equivalent that is not defined in your code but exists non the less when js runs in a browser).
// @types/Foo/index.d.ts
interface Foo {
A();
}
I then add more function to that interface using prototype
// src/monkeypatch.ts
declare global {
interface Foo {
B();
}
}
Foo.prototype.B = function() {};
And use it in my code
// main.ts
import 'src/monkeypatch.ts'; // side effects import
// src/Bar.ts
class Bar {
bar(foo: Foo) {
foo.B();
}
}
So far everything works as expected, my editor is happy, tsc is happy and everything runs just fine in production.
Now I want to set up unit tests and mock out the implementation for the unit test, I create an implementation.
// mocks/Foo.ts
class FooImpl implements Partial<Foo> {
A() {};
}
export { FooIMpl as Foo };
And the test file
// src/Bar.spec.ts
import { Foo } from '../mocks/Foo';
(global as any).Foo = Foo;
import 'monkeypatch'; // patches A with additional methods
import { Bar } from 'Bar';
new Bar().bar(new Foo());
But I am getting the following error as if its not aware of the fact that the intefaces merged or that it was patched:
Argument of type 'FooImpl' is not assignable to parameter of type 'Foo'. Type 'FooImpl' is missing the following properties from type 'Foo': B. ts(2345)
Changing the call site to bar(new Foo() as any);
is a workaround and causes the test to pass but it smells horrible and I want this to work correctly, what am I missing?
The other issue is that I seem to have to use Partial to make the compiler happy, otherwise I get the following error: Class 'FooImpl' incorrectly implements interface 'Foo'. Type 'FooImpl' is missing the following properties from type 'Foo': B