Support TypeScript 6 and 7 without a runtime compiler dependency - #2872
Open
darkbasic wants to merge 1 commit into
Open
Support TypeScript 6 and 7 without a runtime compiler dependency#2872darkbasic wants to merge 1 commit into
darkbasic wants to merge 1 commit into
Conversation
Extract the TypeScript work from darkbasic onto upstream main. Combine the TS6 adaptation in 219be04 with the compiler-free generator in 699ab08, based on upstream PRs openapi-ts#2774 and openapi-ts#2868. Keep this PR independent of the fork's pnpm upgrade, dependency/security updates, and required-only allOf feature. Preserve main's ordinary allOf behavior and generated examples. Generate TypeScript source through string builders instead of the classic compiler API. Remove the generator's TypeScript peer dependency so CLI, ESM, and CommonJS generation work with TS5, TS6, TS7, or no compiler installed. Keep TypeScript as a development dependency for builds and semantic assertions, using TS6.0.3 through the shared workspace catalog. Carry the enhanced Readable/Writable implementation into both the helpers package and generated read/write helpers. Preserve call signatures and built-in methods while resolving markers on other data properties. Keep callable arguments, results, and attached properties opaque. Resolve readonly collection methods and iterators through their element types, preserving readonly indices, length, required numeric properties, and additional data. Retain existing mutable-tuple behavior and lazy recursive array support, with no tuple reconstruction or recursion depth machinery. Keep the any fast path and inline generated readonly-data mappings to avoid collisions with root types named ReadonlyArrayData. Add the string-emitter corrections developed beyond upstream openapi-ts#2868: - Preserve outer array dimensions independently of item source text, including nested arrays, tuples, literals, and composed item schemas. - Parenthesize readonly arrays and lower-precedence type expressions correctly, including rest elements and custom hook-returned types. - Account for quoted strings, templates, comments, and all JavaScript line-comment terminators when composing type expressions. - Escape template literal paths and unusual parameter names safely. - Deduplicate footer helpers by their complete declarations so enum values or comments mentioning helper names cannot suppress output. - Let property hooks control readonly for ordinary properties and $defs. - Recognize root object types with comments or inline formatting and use aliases for nonempty object-shaped $defs under postTransform, including custom mapped types, while preserving empty-root fallback behavior. - Reject obsolete AST inputs and printer options in astToString instead of silently accepting incompatible calls. Correct CommonJS declarations to describe the actual default and named exports by disabling unbuild's incompatible declaration interop transform. Publish @types/js-yaml and json-schema-to-ts because Redocly's public declarations reference them; strict consumers must not have to supply these dependencies themselves. Preserve main's Redocly and tool versions. Make the breaking Node API explicit in English, Japanese, and Chinese: openapiTS resolves to source text, transform/postTransform exchange source strings, transformProperty uses a structured property description, footer declarations are source strings or deferred operations, and inject is emitted verbatim. Replace AST-specific utilities with string builders. Keep astToString as a unary source-string normalizer. Remove deprecated compiler options, fix the nonstrict test rootDir, and use Headers.forEach in the fetch test harness. Test TS5 and TS6 across Node22 and Node24 in CI, including package/framework checks. Keep static lint separate and avoid rerunning helper assertions within a matrix job. Allow TS6 only for the tested existing unbuild, rollup-plugin-dts, and SvelteKit versions whose peer ranges still exclude it. Retain upstream pnpm10.30.3, action-setupv5, and the existing browser CI configuration. Add isolated installed-package checks for TS5.9.3, TS6.0.3, TS7.0.2, and no compiler under Node22/24. Pack both packages without publishing test or script sources, exercise CLI/ESM/CommonJS and all hooks, and compile public API fixtures and generated declarations with strict checking and skipLibCheck=false. Reuse the full helper assertion suite against packed helpers and both mutable/immutable generated helpers. Include negative assertions so accidental any or incorrect array depth cannot pass silently. Provide a major generator changeset and a separate helpers patch changeset so the generator's breaking migration notes do not appear as helper API changes. Update contribution guidance and preserve ordinary allOf tests. Validation on this extracted branch with main's dependency versions: - Frozen pnpm10.30.3 install and changeset release plan pass. - All four TS5.9.3/TS6.0.3 x Node22.23.2/24.19.0 combinations pass 841 tests: generator353, fetch451, react-query37; all eight Turbo tasks run uncached, including package builds, helper assertions, example typechecks, and package export checks. - Package and nonstrict typechecks pass in all four combinations. - All eight packed-consumer combinations pass, including TS7.0.2 and generation with no installed TypeScript compiler. - Static lint, documentation build, and Vue/Svelte/Next example typechecks under TS5 and TS6 pass. - Nine CLI-generated examples from cached schemas exactly match main's snapshots; no example updates are needed. - Independent correctness and maintainability reviews found no blockers; 1,620 allOf differential cases match main's types and callback traces. Browser, macOS, and Windows execution was not rerun locally. TS7 validation covers installed consumers and generated declarations; workspace tooling continues to use and test the classic TS5/TS6 compiler. Based on openapi-ts#2774 Based on openapi-ts#2868 Related to openapi-ts#2841 Co-authored-by: benjamineckstein <13351939+benjamineckstein@users.noreply.github.com> Co-authored-by: im10furry <im10furry@users.noreply.github.com>
🦋 Changeset detectedLatest commit: a8e1738 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
👷 Deploy request for openapi-ts pending review.Visit the deploys page to approve it
|
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.
Changes
Support TypeScript 5, 6, and 7 consumers, including generation without TypeScript installed, by combining the TS6 work from #2774 with the compiler-free generator from #2868. This PR carries over the additional fixes developed in the
darkbasicfork and adds regression and installed-package coverage around both changes. The generator's Node API changes require a major release; the helpers package receives a separate patch release.Addresses #2841 and the compatibility discussion in #2831.
This is a focused extraction against
main. It excludes the fork's separate required-onlyallOffeature, pnpm upgrade, and dependency/security updates. Existing ordinaryallOfbehavior and all nine generated example snapshots are preserved. The only dependency changes serve compiler compatibility or the published declarations.Relationship to the existing PRs
6a805ba5Headers.forEachworkaround.26f4233dreadonlycontrol, stricter migration behavior, declaration packaging fixes, installed-consumer coverage, and completed migration documentation.tsfor callbacks. It also contains CJS declaration and installed-consumer fixes.#2868 already makes the generator usable with TS6 as well as TS7 by removing its compiler API dependency. The separate TS6 work addresses helper semantics, workspace configuration, and regression coverage. This PR includes both sets of changes; it does not require merging #2774 separately.
Credit for the original approaches belongs to the authors of #2774 and #2868. The CJS and consumer-test improvements below are additions beyond #2868, rather than claims of originality across every proposal.
Further work beyond #2774
The original fork comparison is recorded in this comment on #2774. The relevant additions included here are:
--read-write-markersemits the same correctedReadable<T>andWritable<T>behavior asopenapi-typescript-helpers, under both mutable and immutable generation.DateandRegExpkeep their callable methods while visibility markers on their additional data properties are resolved. Callable arguments, results, and attached properties remain opaque. The mapped-type bug also existed under TS5; it was not caused by a TS6 change to whetherDateextendsobject.neverrule.ReadonlyArrayDataremains usable. The package keeps its private alias, and theanyfast path remains available for compiler efficiency.any, lost visibility filtering, incorrect method signatures, or mutable access to readonly positions. Test sources are excluded from published packages.rootDiris corrected, and CI checks TS5/TS6 on Node 22/24 with framework examples. Peer exceptions apply only to the specific existing build-tool and SvelteKit versions tested with TS6.Further work beyond #2868
The string emitter and removal of the compiler dependency come from #2868. The additional work addresses the behavior around that rewrite:
itemsschema always describes an element, even when it emits an array, tuple, literal, or composed type. The outer array is no longer inferred from the rendered text. Nested immutable arrays producereadonly (readonly number[])[]; arrays of union items retain their outer dimension regardless of union order. Rest elements and hook-returned type expressions use the same precedence handling.WithRequired, for example, cannot suppress the real helper.transformPropertyreceives and can overridereadonlyfor ordinary properties and$defs, alongside the existing name, optionality, type, and comment fields.postTransformconfigured, nonempty object-shaped$defsuse aliases so mapped types remain valid. Empty-root fallback behavior is retained.astToString()normalizes source strings and rejects old AST inputs or printer options, instead of silently ignoring incompatible options.@types/js-yamlmoves from development to runtime dependencies, andjson-schema-to-tsis added. Redocly's exposed declarations refer to these packages; strict consumers should not need to discover and install them separately.strict: trueandskipLibCheck: falsefor compiler cases.The single-member union simplification and multiline enum-description fix are inherited from #2868.
Breaking Node API changes
openapiTS()returnsPromise<string>instead ofPromise<ts.Node[]>. The returned body ends with a newline and does not includeCOMMENT_HEADER.transformreturns type source text, or{ schema: string, questionToken: boolean }.postTransformreceives and returns type source text.transformPropertyuses{ name, optional, readonly, type, comment?, indent }. UsetsComment()when constructing JSDoc from this hook.injectis emitted verbatim.astToString()accepts a source string or an array of source strings, joins the fragments, and ensures a trailing newline. AST nodes and printer options are unsupported.postTransformchanges nonempty object-shaped$defsroots to type aliases, allowing custom mapped types.For a simple callback, returning
ts.factory.createTypeReferenceNode("Date")becomes returning"Date". Callbacks that inspect or rewrite arbitrary ASTs require a source-based rewrite. The CLI's basic invocation stays the same.How to Review
Start with
packages/openapi-typescript/src/types.tsanddocs/node.mdfor the public API, then review the source builders insrc/lib/ts.tsand their transformer call sites. The additional behavior beyond #2868 is concentrated in array handling, property mutability, root output, path escaping, and footer helper membership.Review
packages/openapi-typescript-helpers/src/index.tstogether with the generated helper templates inpackages/openapi-typescript/src/transform/index.ts. The package assertions andtest/read-write-helpers.test.tsverify that both forms preserve the same semantics.For packaging and compatibility, review
build.config.ts, the generator'spackage.json,scripts/test-consumer.mjs, its fixtures, and.github/workflows/ci.yml. The repository retainsmain's pnpm 10.30.3, existing dependency versions apart from the changes described above, and existing browser CI configuration.Validation on this branch
These results were rerun on the focused extraction using
main's dependency graph:skipLibCheck: false.main. Generated examples compile with TS6 under the existing example configuration, retaining its DigitalOcean exclusion.allOfcomparison found no type or callback-trace differences frommain.TS7 coverage applies to installed consumers, the public API declarations, and generated types. Workspace build/test tooling remains on the classic TS5/TS6 compiler. Browser, macOS, and Windows tests were not rerun locally; their CI jobs remain in place. Live schema downloads were not refreshed; cached-schema generation verified that no example snapshot changes are needed.
Useful checks after installing dependencies:
The workflow performs the workspace TS5 check by changing the shared catalog to
^5.9.3before installing in that job. Local TS5 validation used a separate workspace copy with its own dependency installation.Checklist
docs/updated, including English, Japanese, and Chinese migration guidance.main. The live-refreshpnpm run update:examplescommand was not run.