Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

isDeepEqual and negation in guard can break type #634

Closed
dartess opened this issue Apr 11, 2024 · 6 comments · Fixed by #635
Closed

isDeepEqual and negation in guard can break type #634

dartess opened this issue Apr 11, 2024 · 6 comments · Fixed by #635
Labels
bug Something isn't working released typing Something type related

Comments

@dartess
Copy link
Contributor

dartess commented Apr 11, 2024

I get never for first isDeepEqual argument and I can't use it:

type Foo = {
    bar: string;
}

function reset(bar: string) {}

function effect(oldValue: Foo, newValue: Foo) {
    if (!R.isDeepEqual(oldValue, newValue)) {
        reset(oldValue.bar);
                    // ^ Property 'bar' does not exist on type 'never'.(2339)
    }
}

demo: https://www.typescriptlang.org/play?#code/JYWwDg9gTgLgBAKjgQwM5wEpwGZQiOAcigFMQSATZQgbgCg6YBPMEuAMQgjgF44BvOnGFwARsigAuOKhhRgAOwDm9AL4NsAVwUBjGMAgK4pVCRgAKcVJlzFSgJQD1dLbv2G4JbNhJ7zEABsKADVkAM0SaU4IABo4BRIAd1DwyI4uR0EROGBsOHMAQgwAOmBUABESEjAAUQBHTTD-IJSIuITksIj7TKFskRMzZpCukmKre3ps9VUgA

@Brodzko
Copy link
Contributor

Brodzko commented Apr 11, 2024

Hmm, R.isDeepEqual returns data is Foo in your case. Negating it, I would expect that "data is not Foo", which would mean never actually sounds correct 🤔 Though I'm pretty sure Typescript cannot reasonably negate type predicates.

Interestingly enough though, the above works with the data-last case, if it helps you as a quick workaround. Not sure why though.

function effect(oldValue: Foo, newValue: Foo) {
    if (!R.isDeepEqual(oldValue)(newValue)) {
        reset(oldValue.bar);
           // ^? is now `Foo`
    }
}

Updated TS Playground

@dartess
Copy link
Contributor Author

dartess commented Apr 11, 2024

Two variables can be of the same type and not be strictly equivalent.
Drawing conclusions about the type of a variable based on the strict equality of its value in this case does not sound correct, imo.
I would suggest removing the typeguard here.

@dartess
Copy link
Contributor Author

dartess commented Apr 11, 2024

quick workaround

Thanks, but it didn't work for me, IRL I use both values in code :)

@eranhirsch
Copy link
Collaborator

Thanks for reporting this; that's a good observation I missed when converting it to a narrowing type. I'll see if I can come up with a fix that would still support some narrowing where it works with typescript.

@eranhirsch eranhirsch added bug Something isn't working typing Something type related labels Apr 11, 2024
@Brodzko
Copy link
Contributor

Brodzko commented Apr 11, 2024

Two variables can be of the same type and not be strictly equivalent.

Drawing conclusions about the type of a variable based on the strict equality of its value in this case does not sound correct, imo.

I think the point was that if two objects are deeply equal, they necessarily are of the same type (since we don't have named types in TS).

Say oldValue was Foo but newValue was Foo | Bar. In that case, if R.deepEquals(oldValue, newValue), it makes total sense to expect newValue to be narrowed to Foo.

Rather than loosening the return type to boolean, I'd prefer fixing this to behave correctly, if possible.

eranhirsch added a commit that referenced this issue Apr 13, 2024
Fixes: #634

Narrowing the result of isDeepEqual is redundant when the type isn't
effectively narrowed because it breaks the rejected/negated path which
would be `never`.

This means that the common use case where both objects are of the same
type and narrowing was meaningless, will now act as a regular boolean
check.
@TkDodo
Copy link
Collaborator

TkDodo commented Apr 13, 2024

🎉 This issue has been resolved in version 1.58.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working released typing Something type related
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants