Skip to content

fix(isDeepKey): improve deep key detection to match strict patterns#1621

Open
ramong26 wants to merge 3 commits intotoss:mainfrom
ramong26:fix/isDeepKey-validation
Open

fix(isDeepKey): improve deep key detection to match strict patterns#1621
ramong26 wants to merge 3 commits intotoss:mainfrom
ramong26:fix/isDeepKey-validation

Conversation

@ramong26
Copy link
Copy Markdown

@ramong26 ramong26 commented Feb 17, 2026

What

  • Improved the isDeepKeyfunction to strictly detect only valid deep key patterns.
  • Now returns false for invalid patterns such as 'a.', '.a', 'a[b', 'a]b]', and 'a][b]'.
  • Returns true only for keys that match valid deep key patterns (e.g., 'a.b', 'a[b]', 'a.b.c', 'a[b][c]').
  • Ensured isKeyuses the same consistent deep property regex for property path detection.

Why

  • The previous implementation returned true for some invalid patterns, which could lead to incorrect behavior.
  • This change ensures that only syntactically valid deep keys are detected, matching the documented examples and improving reliability.

Test

  • Added and updated unit tests in isDeepKey.spec.ts to cover both valid and invalid deep key patterns.
  • Verified that isKey and isDeepKeyare consistent in their detection logic.

- Enhance isDeepKey to return false for invalid patterns like 'a.', '.a', 'a[b', etc., ensuring only valid deep keys are detected.
Copilot AI review requested due to automatic review settings February 17, 2026 10:32
@vercel
Copy link
Copy Markdown

vercel bot commented Feb 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
es-toolkit Error Error Feb 17, 2026 10:49am

Request Review

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens deep-key detection in the compat layer so functions like get/has/unset only treat syntactically valid deep-path strings as deep keys (and otherwise treat the string as a literal property key).

Changes:

  • Refines isDeepKey to reject several previously-accepted invalid patterns.
  • Expands isDeepKey unit tests to cover additional valid/invalid inputs.
  • Adds a null-guard in findIndex’s object-shorthand handling.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
src/compat/array/findIndex.ts Adds explicit handling for doesMatch === null in the object-shorthand branch.
src/compat/_internal/isDeepKey.ts Reworks deep-key detection logic for dot/bracket patterns.
src/compat/_internal/isDeepKey.spec.ts Adds tests for additional invalid patterns and a few more valid cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

expect(isDeepKey('.a')).toBe(false);
expect(isDeepKey('a[b')).toBe(false);
expect(isDeepKey('a]b]')).toBe(false);
expect(isDeepKey('a][b')).toBe(false);
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The updated tests cover a handful of invalid patterns, but they don't cover several false positives the new implementation still allows (e.g. a..b, a.b., a[b][c, a[b]], a[b]c, a.b[). Adding cases like these would prevent regressions and ensure the “strict pattern” behavior described in the PR.

Suggested change
expect(isDeepKey('a][b')).toBe(false);
expect(isDeepKey('a][b')).toBe(false);
expect(isDeepKey('a..b')).toBe(false);
expect(isDeepKey('a.b.')).toBe(false);
expect(isDeepKey('a[b][c')).toBe(false);
expect(isDeepKey('a[b]]')).toBe(false);
expect(isDeepKey('a[b]c')).toBe(false);
expect(isDeepKey('a.b[')).toBe(false);

Copilot uses AI. Check for mistakes.
Comment thread src/compat/_internal/isDeepKey.ts Outdated
Comment on lines +30 to +31
if (dotIndex > 0 && dotIndex < key.length - 1) {
return true;
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dot check only looks at the first '.' and only enforces it isn't the first/last character. This still returns true for syntactically invalid dot paths like a..b (empty segment) or a.b. (trailing dot), which contradicts the PR goal of accepting only strict deep-key patterns. Consider validating the full string (e.g., reject consecutive dots / any empty segment) rather than just indexOf('.') bounds checks.

Suggested change
if (dotIndex > 0 && dotIndex < key.length - 1) {
return true;
if (dotIndex !== -1) {
const segments = key.split('.');
if (segments.length > 1 && segments.every(segment => segment.length > 0)) {
return true;
}

Copilot uses AI. Check for mistakes.
Comment thread src/compat/_internal/isDeepKey.ts Outdated
Comment on lines 34 to 38
let leftBracketIndex = key.indexOf('[');
let rightBracketIndex = key.indexOf(']');
if (leftBracketIndex !== -1 && rightBracketIndex !== -1 && leftBracketIndex < rightBracketIndex) {
return true;
}
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bracket check only verifies that the first '[' appears before the first ']'. It will still return true for invalid/mismatched bracket patterns like a[b][c (unclosed), a[b]] (extra ']'), a.b[ (unclosed), or a[b]c (missing separator). To meet the strict-pattern intent, this likely needs a small parser/regex that validates balanced bracket segments and disallows stray brackets outside of them.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants