feat: add TypeScript 6 support#2774
feat: add TypeScript 6 support#2774benjamineckstein wants to merge 2 commits intoopenapi-ts:mainfrom
Conversation
- Widen peer dep: `^5.x` → `^5.x || ^6.x` - Upgrade devDependency in openapi-typescript-helpers: 5.9.3 → 6.0.2 - Build, tests, and lint all pass with TS6 - No code changes needed Closes openapi-ts#2723
👷 Deploy request for openapi-ts pending review.Visit the deploys page to approve it
|
🦋 Changeset detectedLatest commit: a749a52 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 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 |
…e/Writable types for TS6 In TypeScript 6, `Date extends object` evaluates to `true` (changed from TS5). This caused `Readable<T>` and `Writable<T>` to structurally expand Date, RegExp, and function fields instead of preserving them. Add a guard clause for built-in objects (Date, RegExp, functions) before the `T extends object` branch in both type utilities. Ref: openapi-ts#2723
| : T extends object | ||
| ? { [K in keyof T as NonNullable<T[K]> extends $Write<any> ? never : K]: Readable<T[K]> } | ||
| : T; | ||
| : T extends Date | RegExp | ((...args: never[]) => unknown) |
There was a problem hiding this comment.
In TypeScript 6, Date extends object now evaluates to true (it was false in TS5). Without this guard, Readable<T> would structurally expand Date fields into { toString: {}; toDateString: {}; ... } instead of preserving the Date type — making any schema containing Date fields incompatible with itself when accessed through FetchResponse.
This guard preserves built-in objects (Date, RegExp, functions) by matching them before the generic T extends object branch. It's backward compatible with TS5 since these types were never matched by T extends object there.
The Dependabot group update bumped typescript to ^6.0.2, but openapi-typescript@7.13.0 still declares peer typescript ^5.x, so npm ci fails to resolve. Revert just the typescript bump (keep the other five: @types/node, @vitest/coverage-v8, msw, oxlint, vitest) and regenerate the lockfile against 5.9.3. Add a temporary dependabot.yml ignore on typescript semver-major bumps so the same mismatch doesn't keep getting proposed. Remove the ignore once openapi-typescript ships TS 6 support (openapi-ts/openapi-typescript#2774).
* Bump the npm-deps group across 1 directory with 6 updates Bumps the npm-deps group with 5 updates in the /typescript directory: | Package | From | To | | --- | --- | --- | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.5.0` | `25.5.2` | | [@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8) | `4.1.0` | `4.1.2` | | [msw](https://github.com/mswjs/msw) | `2.12.14` | `2.13.0` | | [oxlint](https://github.com/oxc-project/oxc/tree/HEAD/npm/oxlint) | `1.56.0` | `1.58.0` | | [typescript](https://github.com/microsoft/TypeScript) | `5.9.3` | `6.0.2` | Updates `@types/node` from 25.5.0 to 25.5.2 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `@vitest/coverage-v8` from 4.1.0 to 4.1.2 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/coverage-v8) Updates `msw` from 2.12.14 to 2.13.0 - [Release notes](https://github.com/mswjs/msw/releases) - [Changelog](https://github.com/mswjs/msw/blob/main/CHANGELOG.md) - [Commits](mswjs/msw@v2.12.14...v2.13.0) Updates `oxlint` from 1.56.0 to 1.58.0 - [Release notes](https://github.com/oxc-project/oxc/releases) - [Changelog](https://github.com/oxc-project/oxc/blob/main/npm/oxlint/CHANGELOG.md) - [Commits](https://github.com/oxc-project/oxc/commits/oxlint_v1.58.0/npm/oxlint) Updates `typescript` from 5.9.3 to 6.0.2 - [Release notes](https://github.com/microsoft/TypeScript/releases) - [Commits](microsoft/TypeScript@v5.9.3...v6.0.2) Updates `vitest` from 4.1.0 to 4.1.2 - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.2/packages/vitest) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 25.5.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-deps - dependency-name: "@vitest/coverage-v8" dependency-version: 4.1.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-deps - dependency-name: msw dependency-version: 2.13.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-deps - dependency-name: oxlint dependency-version: 1.58.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: npm-deps - dependency-name: typescript dependency-version: 6.0.2 dependency-type: direct:development update-type: version-update:semver-major dependency-group: npm-deps - dependency-name: vitest dependency-version: 4.1.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: npm-deps ... Signed-off-by: dependabot[bot] <support@github.com> * Keep typescript on 5.9.x until openapi-typescript supports TS 6 The Dependabot group update bumped typescript to ^6.0.2, but openapi-typescript@7.13.0 still declares peer typescript ^5.x, so npm ci fails to resolve. Revert just the typescript bump (keep the other five: @types/node, @vitest/coverage-v8, msw, oxlint, vitest) and regenerate the lockfile against 5.9.3. Add a temporary dependabot.yml ignore on typescript semver-major bumps so the same mismatch doesn't keep getting proposed. Remove the ignore once openapi-typescript ships TS 6 support (openapi-ts/openapi-typescript#2774). * Raise engines.node floor to >=20 (drop EOL Node 18) Node 18 reached end-of-life on 2025-04-30. Currently supported Node releases are 20 (Maintenance LTS until 2026-04-30), 22 (LTS), and 24. Lift the consumer-facing engines floor accordingly. Dev toolchain (oxlint, @inquirer/*, etc.) already requires Node 20.x or newer at the transitive level — that's fine for contributors and separate from the published SDK's runtime contract. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Jeremy Daer <jeremy@37signals.com>
…tream (#73) ## Summary - eslint 10 + matched plugins: blocked on react-hooks 7.x's expanded recommended preset surfacing ~60 real lint errors. Need a code-fix sweep first. - typescript 6: blocked on openapi-typescript widening its peer dep to TS 6 ([upstream PR #2774](openapi-ts/openapi-typescript#2774)). Adds ignore rules so Dependabot stops opening unmergeable PRs for these majors. Closing #61 and #65 in tandem. ## Test plan - [ ] CI green on this PR (lint/typecheck/tests don't depend on Dependabot config) - [ ] Verify Dependabot won't re-open the bumps next Monday --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
What is missing to merge this PR? ... now it contains merge conflicts ... |
The .npmrc workaround is metadata-only — npm ls confirms typescript@6.0.3 is the only version installed. Add a TODO link to openapi-ts/openapi-typescript#2774 so it's clear when the flag can come off.
…degen (#1428) * [#1403] Frontend-react data layer: HTTP client + TanStack Query + OpenAPI codegen HTTP wrapper at src/lib/http.ts handles bearer + CSRF, /api/v1/<resource> to /api/v1/g/{slug}/<resource> rewriting, single-flight refresh on 401, and surfaces non-2xx as HttpError so React Query can react via onError. Storage keys (inventario_token, inventario_csrf_token, inventario_user) match the legacy Vue frontend so a session survives the dual-bundle INVENTARIO_FRONTEND switch (#1401). QueryClient defaults: staleTime 30s, retry 1 (skipped for 4xx). Providers wraps QueryClientProvider + ReactQueryDevtools (dev only) + ThemeProvider; main.tsx uses it. OpenAPI codegen converts go/docs/swagger.json (Swagger 2.0) to OAS3 via swagger2openapi, then emits src/types/api.d.ts via openapi-typescript. Exposed as npm run codegen / codegen:check, make codegen-frontend-react / codegen-frontend-react-check, and a new frontend-react-codegen workflow that fails the build on drift. Sample feature slice at features/session/ proves the layer end-to-end: useCurrentUser query and an optimistic useLogout mutation with cache rollback on error. Tests: 40 (Vitest + MSW v2) covering each prefix rewrite, /auth/* pass-through, slug encoding, CSRF only on mutations + rotation from response headers, AbortSignal forwarding, 4xx/5xx HttpError, the full refresh+retry path, refresh-failure clear+navigate, background /auth/me 401 non-redirect, and single-flight refresh dedup. .npmrc pins legacy-peer-deps=true because openapi-typescript@7 declares peer typescript@^5.x while the scaffold is on TS 6 — the peer is build-time only and emit goes through openapi-typescript's bundled compiler, so the mismatch is benign. Drop the flag once openapi-typescript ships TS 6 support. Closes #1403. * [#1403] Document legacy-peer-deps workaround with upstream PR link The .npmrc workaround is metadata-only — npm ls confirms typescript@6.0.3 is the only version installed. Add a TODO link to openapi-ts/openapi-typescript#2774 so it's clear when the flag can come off. * [#1403] Address CI failures + Copilot review - Dockerfile: copy frontend-react/.npmrc into the React builder stage so npm ci picks up legacy-peer-deps=true (Build linux/{amd64,arm64} fix). - ApiResponse helper: try application/vnd.api+json first then fall back to application/json, and accept any 2xx status. Most Inventario endpoints serve JSON:API, so the previous 'application/json'-only shape resolved to never for them. - useLogout: removeQueries() instead of setQueryData(..., null) so the cache stays type-true to the query's CurrentUser shape; consumers see data === undefined rather than a surprise null at runtime. - Drop the meCalls > 1 assertion in the optimistic-logout test — it encoded an implementation detail (invalidate-after-remove timing) that did not survive the removeQueries switch. New assertion pins the real invariant: cache stays cleared after a successful logout. - Prettier: re-format http.ts, http.test.ts, types/index.ts, generated api.d.ts, and the session test (Lint Frontend (React) job fix). * [#1403] Exclude generated api.d.ts from prettier The previous commit's prettier sweep reformatted src/types/api.d.ts, which then disagreed with what scripts/codegen.mjs produces — the codegen-drift CI job rejected the result. Add .prettierignore to keep the generator's emit untouched, and restore api.d.ts to the codegen-true output.
Summary
Add full TypeScript 6 support — not just the peer dep range, but also a fix for a TS6 behavioral change that breaks
Readable<T>andWritable<T>.Changes
Peer dep & devDependency (commit 1):
packages/openapi-typescript/package.json: widen peer dep^5.x→^5.x || ^6.xpackages/openapi-typescript-helpers/package.json: upgrade devDependency5.9.3→6.0.2Fix Readable/Writable types (commit 2):
In TypeScript 6,
Date extends objectevaluates totrue(changed from TS5). This causedReadable<T>andWritable<T>to structurally expand built-in objects likeDateinto{ toString: {}; toDateString: {}; ... }instead of preserving theDatetype.Added a guard clause for
Date | RegExp | ((...args: never[]) => unknown)before theT extends objectbranch in both type utilities, preserving built-in objects. This fix is backward compatible with TS5.Changeset: patch release for both
openapi-typescriptandopenapi-typescript-helpersValidation
pnpm run build— all 4 packages build successfullypnpm test— all 7 test suites passpnpm run lint— cleanContext
Readable<T>/Writable<T>reported by @yamafaktory in Add support for TypeScript 6 #2723