Skip to content

Proposal: Discussing behavioral mismatches and possible improvement for isMatch #1504

@sen2y

Description

@sen2y

Proposal: Improve isMatch behavioral consistency

Hi!

While fixing several isMatch issue(#1399), I found cases where Lodash and compat show different results:

Case Lodash compat
Some partial-match cases ❌ incorrect ✅ correct

Since compat’s core goal is to help migration by providing full behavioral parity with Lodash,
this mismatch should be fixed — compat should produce the same result as Lodash.

✅ However, the behavior in Lodash itself is buggy
❌ So simply aligning compat to Lodash is also not ideal for users

In other words…

We need to fix the mismatch
but also fix the root cause that causes confusion


🔍 Example

Image

Especially with Set / Map subset matching, Lodash returns unexpected results.

Image

Additionally, since Lodash is not maintained by Toss,
it can be difficult to decide which behavior compat should follow in cases like this.


Related Lodash Issue (#3887)

Lodash maintainer’s reasoning:

“When there's nothing to match, everything matches.”

However, the actual behavior varies:

target source Lodash result
{a:1} {} true ✅
{a:1} null true ✅
{a:1} 123 true ✅
{a:1} '' true ✅
{a:1} 'abc' false
  • Same condition → different results depending on recursion depth
  • Primitive values always match (except strings)

Since this behavior is not clearly documented,
it can be unintuitive and difficult to predict —
meaning users may reasonably be confused by these results.


🤔 Depth-dependent behavior

isMatch('bar', {})                               // true (top level)
isMatch({ value: 'bar' }, { value: {} })         // false (nested)

❌ difficult for users to anticipate

✅ Proposal

compat direction es-toolkit enhancement
Follow Lodash behavior exactly Provide a clearer and more consistent alternative API
Ensures seamless migration experience Improves correctness & predictability for users

The new API could:

  • Remove “primitive source always matches” rule
  • Apply consistent subset rules for Set / Map
  • Avoid depth-dependent behavior
  • Clearly follow:
    source ⊆ target → true

🙏 Request for maintainer input

To support smooth migration, compat should align with Lodash’s behavior —
but preserving behavior that is buggy or confusing in practice may lead to unintended issues.

So I’d like to propose introducing a new, more predictable isMatch-style API in es-toolkit, independent from Lodash’s quirks.

In isMatch(target, source), the fact that results can differ based on recursion depth — and that primitive source values almost always return true without clear documentation — can be confusing for users.
These implicit and inconsistent rules make it difficult to confidently understand what it means for the source to be “matched” by the target in real-world scenarios.

A new API that provides consistent and intuitive matching rules would significantly improve the developer experience.

Would this be something worth addressing in es-toolkit?
I’d love to hear your thoughts! 😊

If this proposal sounds reasonable,
I would be happy to try implementing an initial version —
and would greatly appreciate any guidance or feedback along the way! 🙌

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions