Repository navigation
TS5115 in published Zod 4.5–4.6 types after #64372 #64605
Description
Activity
- addedNeeds InvestigationThis issue needs a team member to investigate its status.This issue needs a team member to investigate its status.
on Oct 6, 2026 I traced this one while checking Zod 4.6.5 on the 7.1 nightlies.
Cause: #64372 stopped
resolveObjectTypeMembersfrom storing declared members before the base types resolve. When a base type argument refers back to the type, member resolution starts over and instantiates the same bases again until the depth limit.In Zod,
$ZodRecordInternals<ZodString, ZodJSONSchema>has$InferZodRecordInputin its base type arguments. That readsoptinthroughIsOptionalInover the union members, which leads back to$ZodRecordInternals<ZodString, ZodJSONSchema>itself. But that type declaresoptin, andaddInheritedMembersnever replaces a declared value member, so the answer is known before the bases resolve. The cycle isn't real. The reduction above reaches the same point throughisStringIndexSignatureOnlyType.A fix that keeps what #64372 guarantees: while
resolveObjectTypeMembersadds inherited members, keep the type's declared members on a small stack. In that window:getPropertyOfTypeExreturns a value member the type declares itself, the same symbol the resolved members end up holdingisStringIndexSignatureOnlyTypeWorkerreturns false for a type that declares a property
Every other query resolves the members again, as it does today, and nothing partial is stored on the type. It's 54 lines in
checker.go.Results at 673a5f1:
- the reduction above, and
zod@4.6.5withz.json()in arrays, records, unions, tuples, maps and.pipe(), withskipLibCheckon and off: all clean TestLocal, the fourslash tests (includingTestNoGhostErrors) and the checker tests pass- one baseline moves:
mutuallyRecursiveInference.errors.txtloses the TS5114 that Restore idempotency toresolveObjectTypeMembers#64372 added. I think that one was a false cycle too, sinceX[X['a']]only reads membersXdeclares.keyofGenericExtendingClassDoubleLayerkeeps its TS5115.
Happy to open a PR if this direction works for you.
Confirmed that this still reproduces with
typescript@7.1.0-dev.20261009.1andzod@4.6.5, using a minimal standalone project. The same project passes withtypescript@7.0.2.index.ts:import * as z from 'zod'; const item = z.object({ data: z.json() }); export const value: z.infer<typeof item> = { data: 1 };
tsconfig.json:{ "compilerOptions": { "strict": true, "noEmit": true, "module": "preserve", "moduleResolution": "bundler", "target": "esnext", "skipLibCheck": true }, "files": ["index.ts"] }Running
tsc -p . --pretty falsewith the nightly produces:index.ts(5,44): error TS5115: Instantiations of the following types appear infinitely circular: '$ZodTypeInternals', '$InferZodRecordInput', 'IsOptionalIn'.Zod TypeScript 7.0.2 TypeScript 7.1.0-dev.20261009.1 4.3.6 Pass Pass 4.6.5 Pass TS5115 The version comparison is for this reproduction only. It independently confirms the affected-version range already reported here; it does not establish that every older-version schema is unaffected.
The Rust port also tracks this upstream regression in pingdotgg/ts-rust#20. Adding this nightly confirmation here rather than opening a duplicate.
Tobias Fu (@realtobyfu), please review the standalone reproduction and version comparison above.
After #64372 Zod 4.5.0-4.6.5 break in TS 7.1 nightlies. I'm merging a fix Zod side, but the affected versions account for ~62M weekly downloads. In the long term I think it's a good price to pay for the improved recursive inference stuff, and not that many people use
z.json(), but just wanted to make sure all options were explored for avoiding this break (as long is it doesn't involve dropping any functionality from #64372 et al). 👍🔎 Search Terms
TS5115, "appear infinitely circular", base type arguments, zod, 64372
🕗 Version & Regression Information
resolveObjectTypeMembers#64372, first in7.1.0-dev.20260929.1.7.0.2and the commit before Restore idempotency toresolveObjectTypeMembers#64372 are fine. Still present in7.1.0-dev.20261002.1.⏯ Playground Link
No response
💻 Code
With the published package (
zod@4.6.5,skipLibCheck: true):🙁 Actual behavior
TS5115 "Instantiations of the following types appear infinitely circular" on
RecordSchema<Json>. The same shape is Zod'sz.json()type, so Zod 4.5.0 through 4.6.5 fail on 7.1:skipLibCheck: false, every project that imports Zod gets TS5115 from Zod's own declarationsskipLibCheck: true,z.array(z.json()),z.record(z.string(), z.json())or.parse()on an object holdingz.json()reports it in user code, and the record's input type becomesRecord<string, any>🙂 Expected behavior
No error, as in 7.0.2.
Additional information about the issue
Those versions get about 62M of Zod's 365M weekly npm downloads. The member-declaration fix from #64372 (comment) is merged in colinhacks/zod#6645 and goes out in the next Zod release, but projects that stay on 4.5.0–4.6.5 will still break when they move to 7.1.