Conversation
JavaScript object keys are always strings, so z.record(z.number(), z.any()) was previously impossible to parse. Now when a key fails validation with 'invalid_type' + 'expected: number', we check if the string key is a valid numeric string and retry parsing with Number(key). Changes: - Add numeric string fallback in $ZodRecord parse logic - Fix missing $ anchor in regexes.number pattern - Add tests for numeric string keys - Remove outdated 'Note on numeric keys' from docs Closes #5521
z.record()
There was a problem hiding this comment.
Solid implementation. Found one typo in the docs where a variable name doesn't match its usage. The approach of validating numeric string keys by converting to Number(key) while preserving string keys in the output correctly mirrors JavaScript's behavior.
packages/docs/content/api.mdx
Outdated
|
|
||
| ```ts | ||
| const numberKeys = z.record(z.number(), z.string()); | ||
| schema.parse({ |
There was a problem hiding this comment.
Variable name mismatch: the schema is defined as numberKeys on line 1867 but referenced as schema here.
There was a problem hiding this comment.
nice catch fix this.
I also think you should take the result value from retryResult, re-stringify it, and use that as the new key. it's possible there are numeric keyType schemas that perform transforms/calculations.
There was a problem hiding this comment.
Fixed by renaming to numberKeys
There was a problem hiding this comment.
Fixed by stringifying the transformed result value
There was a problem hiding this comment.
Pull request overview
This PR improves support for numeric keys in Zod's record schema by implementing a fallback mechanism that validates numeric string keys when using z.number() as the key type. This enhancement aligns Zod's behavior more closely with TypeScript's type system, which automatically converts numeric object keys to strings at runtime.
Key changes:
- Fixed regex pattern for number validation by adding end-of-string anchor
- Added numeric string key fallback logic in record validation
- Updated documentation with examples and removed outdated warning about numeric keys
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| play.ts | Updated import path for development/testing purposes |
| packages/zod/src/v4/core/schemas.ts | Implemented numeric string key fallback in record validation logic |
| packages/zod/src/v4/core/regexes.ts | Fixed number regex pattern by adding missing end-of-string anchor |
| packages/zod/src/v4/classic/tests/record.test.ts | Added comprehensive tests for numeric string key validation |
| packages/docs/content/api.mdx | Updated documentation with new numeric key support examples and removed outdated caveat |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
packages/docs/content/api.mdx
Outdated
|
|
||
| ```ts | ||
| const numberKeys = z.record(z.number(), z.string()); | ||
| schema.parse({ |
There was a problem hiding this comment.
The variable name schema is used but it was defined as numberKeys on line 1867. This will cause a runtime error.
| schema.parse({ | |
| numberKeys.parse({ |
| }); | ||
|
|
||
| // further validation is also supported | ||
| const intKeys = z.record(z.int().step(1).min(0).max(10), z.string()); |
There was a problem hiding this comment.
The chaining .int().step(1) is redundant because .int() already ensures the value is an integer, which means it's inherently a multiple of 1. Consider simplifying to just .int().min(0).max(10) or using .step() with a more meaningful value (e.g., .step(2) for even integers).
| const intKeys = z.record(z.int().step(1).min(0).max(10), z.string()); | |
| const intKeys = z.record(z.int().min(0).max(10), z.string()); |
|
|
||
| z.string().slugify().parse("Hello World"); | ||
| // => "hello-world" | ||
| import * as z from "./packages/zod/src/v4/index.js"; |
There was a problem hiding this comment.
Unused import z.
| import * as z from "./packages/zod/src/v4/index.js"; |
|
Fixed both review comments and pushed changes. |
- Fix docs: use `numberKeys` instead of `schema` in example - Fix implementation: stringify transformed numeric keys for consistency
Closes #5521