ts-auto-mock: [Issue] Version 2.3.4 created a type error with the `createMock` function
Subject of the issue
The latest release 2.3.4 related to the issue #458 fixed an error and also created a new one.
Your environment
- ts-auto-mock version: 2.3.4
- typescript version: 3.9.7
- node version: 13.7.0
- npm version: 6.14.6
Steps to reproduce
Test:
client = createMock<Client>({
user: {
setPresence: setPresenceMock,
},
});
The new error is on user
Error:
TS2322: Type '{ setPresence: jest.Mock<Promise<Presence>, any>; }' is not assignable to type 'PartialObjectDeep<ClientUser>'.
Types of property 'valueOf' are incompatible.
Type '() => Object' is not assignable to type '(() => string) & (() => Object)'.
Type '() => Object' is not assignable to type '() => string'.
Type 'Object' is not assignable to type 'string'.
Fake Client class:
export class Client {
public user: ClientUser | null;
}
Fake ClientUser class:
export class ClientUser {
public setPresence(data: PresenceData): Promise<Presence>;
}
Expected behavior
No error.
Actual behavior
Type error.
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 18 (17 by maintainers)
Are we okay to close this one? @C0ZEN
I realised that the problem is in how javascript works. When you create a new object with
{}you’re actially creating an object with prototype Object, meaning that in the type you also have methods liketoStringandvalueOf.This means that when you write:
in terms of typings is the same as writing:
Object is defined like this:
so this happens:
The type of
valueOfdoesn’t match the type ofvalueOfdefined in ClientUser (that isvalueOf: () => string) and the typings are failing.All of this to say that the error makes sense. I think the only thing we can do about this is updating PartialDeep to be relaxed when using Object. In my mind we should change the name of the type and make it specific for the override parameter (something like MockOverrideValues. but better). We know that if the property is part of the prototype it doesn’t get copied over:
_.merge({ valueOf: function() { return "123"; }}, {}).valueOf() === "123"this means that in PartialDeep when we get to the Object case we should strip it of its prototype properties fixing this bug.Let me know if I made any mistakes
I don’t think it’s an issue on Discord js. They are entitled to override valueOf. I’ll keep these issues open. We’ll try and find a better approach 😃 Thanks for investigating and reporting those issues.
In my opinion the best approach, for now, its to re implement valueOf. That would also solve the Infinite issue that you are facing and you can remove the casting.
@C0ZEN . I’ve reproduce the issue just using Partial from typescript
Yeah, I agree! I didn’t realise that this change may impact a lot of scenario, I thought it was just a better type 😃.
I’ll make the Partial Deep more relaxed to avoid these scenarios until we’ve found a better solution
Cool, thanks @C0ZEN.
The issue is related to the default implementation in an object of valueOf.
The deepPartial that has been added in 2.2.4 is much smarter and it does consider functions.
objectshave by default valueOf.I’m not sure yet 100% if there is a way to workaround that in the deepPartial. I’ll let you know.
In the meantime I would recommend to cast the type.