Skip to content

spell a self-referencing untagged map member as an index signature, where the mapped type cycled - #233

Merged
eburgos merged 1 commit into
masterfrom
untagged-map-index-signature
Aug 11, 2026
Merged

spell a self-referencing untagged map member as an index signature, where the mapped type cycled#233
eburgos merged 1 commit into
masterfrom
untagged-map-index-signature

Conversation

@eburgos

@eburgos eburgos commented Aug 11, 2026

Copy link
Copy Markdown
Owner

A self-recursive untagged enum whose recursive member is a map generates a TypeScript type alias that references itself through Partial<Record<string, Self>>. TypeScript resolves mapped types while it resolves the alias declaring them, so the alias is refused outright: error TS2456: Type alias circularly references itself. The array member never had this problem — only the map spelling did.

The fix is spelling-only: when the map's value type references the enclosing self type (the same test the zod renderer already applies for its z.lazy deferral), the member is written as the index-signature object it is equal to — { [key: string]: V | undefined } — which TypeScript resolves lazily. Every other map keeps the byte-identical Partial<Record<..>>: non-recursive maps, array-wrapped maps (the wrap already defers), and maps whose key does not spell as string or number (an index signature has no parameter type for those; that keyed-by-enum case is tracked separately). Zod and JSON Schema surfaces are untouched.

Tests pin the new spelling on the recursive fixture, the preserved spelling on a new non-recursive one, and the negative assertions on both; verified externally with tsc --strict: the new alias compiles clean, the old spelling reproduces TS2456. Full feature-combination matrix green.

@eburgos
eburgos merged commit 88f1b52 into master Aug 11, 2026
1 check passed
@eburgos
eburgos deleted the untagged-map-index-signature branch August 11, 2026 13:30
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.

1 participant