fix(typescript): emit named type alias for root-level array types#3033
Open
schani wants to merge 6 commits into
Open
fix(typescript): emit named type alias for root-level array types#3033schani wants to merge 6 commits into
schani wants to merge 6 commits into
Conversation
) TypeScript collapsed a root-level array-of-objects type into a single interface named after the array (using directlyReachableSingleNamedType), dropping the array wrapper entirely and emitting no array type alias. Other languages such as Go correctly emit a named array alias plus a separately named object type. Fix: override namedTypeToNameForTopLevel in TypeScriptRenderer to stop collapsing ArrayType top levels into their item type, and emit an `export type Foo = Bar[];` alias for root-level array types, updating converter signatures/usage comments to reference it. Added test/inputs/schema/root-array-ref.schema (+ .1.json sample) as an end-to-end fixture, and test/unit/typescript-root-array-schema.test.ts to assert the exact naming/structure (fixture round-trip tests alone can't express that). Fixes #1309 Co-Authored-By: gpt-5.6-sol via pi <noreply@openai.com>
Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts
The new root-array-ref.schema fixture is a top-level array whose item type carries its own title. Three languages cannot round-trip it and were failing CI: - kotlinx: top-level arrays render as `typealias TopLevel = JsonArray<T>`, which doesn't compile (same documented limitation as union.schema). - php: the fixture driver does not support top-level arrays (same as union.schema). - typescript-zod: the renderer emits only the titled item schema (SomeObjectSchema) and no TopLevelElementSchema, so the driver can't locate a top-level schema to parse the array against. Skip the fixture for these three, mirroring the existing union.schema precedent, rather than weakening the fixture for languages that handle it correctly. The positive and negative cases still run for TypeScript and the other schema languages. Co-Authored-By: Claude <noreply@anthropic.com>
…uired
The root-array-ref negative sample ([{}], an array element missing the
required "name" property) relies on required-property enforcement. Four
more languages already skip required.schema because their generated code
or driver cannot detect a missing required property, so the new fixture's
fail sample is likewise not rejected and the fixture fails:
- cjson: required properties absent are not checked.
- swift: on Linux the missing-required-property failure is not rejected.
- haskell: the driver encodes the Maybe result, so a failed decode prints
null and exits 0.
- elixir: struct keys cannot be enforced at runtime.
Skip root-array-ref.schema for each, mirroring their existing
required.schema skips. The positive and negative cases still run for the
languages that do enforce required (TypeScript, C#, Java, Rust, etc.).
Co-Authored-By: Claude <noreply@anthropic.com>
Generated-output differences70 files differ — 45 modified, 25 new, 0 deleted |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
TypeScript did not generate correct types when a JSON Schema's root type is an array of objects.
For this schema:
{ "$ref": "#/definitions/GetResp", "definitions": { "GetResp": { "title": "GetResp", "type": "array", "items": { "$ref": "#/definitions/SomeObject" } }, "SomeObject": { "title": "SomeObject", "type": "object", "additionalProperties": false, "properties": { "name": { "type": "string" } }, "required": ["name"] } } }TypeScript generated:
— the array wrapper was silently dropped and the object interface was named after the array (
PR, from the root array's title/filename) instead of after the object (SomeObject), and there was no named array type at all.Go, by contrast, correctly generates
type PR []SomeObjectplus a separatetype SomeObject struct {...}.Root cause
TypeScriptRendererinheritedJavaScriptRenderer#namedTypeToNameForTopLevel, which usesdirectlyReachableSingleNamedTypeto collapse a root type onto the single named type reachable through it — including through anArrayType. For a root array of objects, this assigns the top-level name to the item object type instead of the array itself, and TypeScript (unlike some other languages) never separately emits a named alias for array top levels, so the array wrapper disappears entirely.Fix
In
packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts:namedTypeToNameForTopLevelto returnundefinedforArrayType, so root-level arrays keep their own top-level name instead of collapsing onto their item type (this mirrors the same pattern already used by other renderers, e.g.DartRenderer,GolangRenderer,CSharpRenderer).export type <Name> = <Item>[];for root-level array types inemitTypes.Convertclass's method signatures and in the "how to use" usage comment.Flow and other renderers are unaffected.
Test coverage
test/inputs/schema/root-array-ref.schema(+.1.jsonsample) — new end-to-end JSON Schema fixture exercising a root-level array of a named object type, run via the existingschema-*fixture machinery for every language (compiles/round-trips for all languages, including TypeScript).test/unit/typescript-root-array-schema.test.ts— unit test asserting the exact generated structure (export interface SomeObject,export type PR = SomeObject[];, and thatexport interface PRis not generated), since the fixture round-trip test alone can't express "these exact type names/structure must be produced."Verification (local)
npm run buildpasses.QUICKTEST=true FIXTURE=schema-typescript script/test— full suite passes for all schema fixtures including the newroot-array-ref.schema; the only failure (vega-lite.schemaTS2411 errors fromtsc) was confirmed to be pre-existing on unmodified master (verified by stashing this fix and re-running), unrelated to this change.npx vitest run test/unit— all 164 unit tests across 26 files pass, including the new test.Fixes #1309
🤖 Generated with Claude Code