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

[Feature Request]: Object property predicates like hasProp (includes proof of concept) #461

Open
airjp73 opened this issue Jan 12, 2024 · 15 comments · May be fixed by #515
Open

[Feature Request]: Object property predicates like hasProp (includes proof of concept) #461

airjp73 opened this issue Jan 12, 2024 · 15 comments · May be fixed by #515
Labels
feature request New feature or request good first issue Good for newcomers

Comments

@airjp73
Copy link
Contributor

airjp73 commented Jan 12, 2024

I often find myself wanting to filter an array based on whether or not a property exists or that has a property of a certain value (like when working with discriminated unions).

I'm wondering if there's interest in adding some helpers like hasNonNilProperty or hasPropertyWithValue to the library. I'm happy to work on a PR if this seems like something reasonable to add.

I made a Typescript Playground with a couple contrived examples of the type of predicates I'm hoping to add helpers for. edit: see next comment for playground

@airjp73
Copy link
Contributor Author

airjp73 commented Jan 19, 2024

I was playing around with this idea a bit more and I think three helpers would be enough to cover any case I could think of.

  • hasProp - simply determines if an object has the given prop and narrows the type accordingly
  • hasPropSatisfying - everything hasProp does but also checks that the prop satisfies the provided predicate
  • shallowEquals - Does a shallow === comparison. Useful for narrowing discriminated unions.

I implemented a proof of concept for this in this typescript playground.

@airjp73 airjp73 changed the title [Feature Request]: Object property predicates (e.g. hasProperty) [Feature Request]: Object property predicates like hasProp (includes proof of concept) Jan 19, 2024
@eranhirsch
Copy link
Collaborator

Hey, sorry for the long delay in getting back to you. I'm supportive of all of these if you want to send a PR to add them.

shallowEquals should be named isEquals. We need to deprecate the existing equals function and rename it isDeepEquals in a later release of v2.

@TkDodo
Copy link
Collaborator

TkDodo commented Feb 11, 2024

shallowEquals should be named isEquals

hmm whats the reasoning here? Isn't shallowEquals and deepEquals an established naming pattern?

anyway, I agree with deprecating equals because it's unclear what it does and we could just make it an alias of the deep equals function

@TkDodo
Copy link
Collaborator

TkDodo commented Feb 11, 2024

isEqual and isDeepEqual are also fine if we want functions that return a boolean to start with is or has. But I've never seen isEquals...

@eranhirsch
Copy link
Collaborator

I'm very pedantic, so I like the convention of isXXX for boolean functions; I like it so much that I even prefer to avoid hasXXXX when I can and consider the isXXX convention a syntactic requirement. At facebook all async functions had to be called genXXXX, as in async function genFoo() and there were lint rules (maybe even compiler warnings) to protect this.

@eranhirsch
Copy link
Collaborator

@TkDodo - just realized you were referring to the plural 's' at the end of isEquals and not the is part. I totally agree on that!

To summarize, we should have an isEqual (for shallow equality checks) and isDeepEqual.

@eranhirsch eranhirsch added feature request New feature or request good first issue Good for newcomers labels Feb 12, 2024
@airjp73
Copy link
Contributor Author

airjp73 commented Feb 12, 2024

No worries on response times. I totally get it! 😁

I'll see if I can get a PR up this week.

@TkDodo
Copy link
Collaborator

TkDodo commented Feb 16, 2024

To summarize, we should have an isEqual (for shallow equality checks) and isDeepEqual.

could we explicit and do isShallowEqual and isDeepEqual ?

But looking at the PR, it says that:

isEqual does a shallow, Object.is equality comparison and acts as a type guard

Object.is is an equal comparison, but it's not "shallow". What is commonly understood as shallow equality is that objects and arrays are compared one level deep, so isShallowEqual({ a: 'foo' }, { a: 'foo' } would be true.

Object.is does a referential equality comparison. So do we then need 3 functions?

@airjp73
Copy link
Contributor Author

airjp73 commented Feb 18, 2024

Good point of clarification. I misunderstood "shallow equality" to be essentially a synonym for "referential equality". I'm primarily interested in comparing primitives so I'm down for whichever approach you both think is best.

@TkDodo
Copy link
Collaborator

TkDodo commented Feb 18, 2024

my suggestion would be:

  • isEqual - does a referential comparison with Object.is
  • isShallowEqual - does a shallow equal by comparing one level deep, e.g. how zustand does it
  • isDeepEqual - deep equals comparison, like we do now with equals

also:

  • deprecate equals and basically alias it for isDeepEqual

@eranhirsch is that alright ?

@eranhirsch
Copy link
Collaborator

Sounds good!

@eranhirsch
Copy link
Collaborator

Well... one point, about discoverability, If we put everything under a single namespace it's easier for people to find it, isEqual.shallow, isEqual.deep, and isEqual, otherwise they don't share a prefix and typeahead wouldn't show the other... I don't think it's necessarily a better API, but we can talk about it and see how we feel.

@TkDodo
Copy link
Collaborator

TkDodo commented Feb 18, 2024

disadvantage is that those wouldn't be tree-shakable, and we don't have those "namespaces" anywhere else. The only thing this is currently used for is for .strict, and .strict doesn't have a separate runtime implementation - only difference is type-level, so the tree-shaking problem doesn't apply. I don't think we should open this box to have different impls on "namespaces" ?

@eranhirsch
Copy link
Collaborator

The other alternative is isEqualShallow isEqualDeep and isEqual...

@TkDodo
Copy link
Collaborator

TkDodo commented Feb 18, 2024

if the issue is discoverability, I think searching for equal should yield all 3 results. algolia docsearch would help here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request good first issue Good for newcomers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants