TypeScript Go (tsgo) Migration
Context and Problem Statementβ
To prepare for TypeScript 7.0 and leverage advanced type checking features, we evaluated integrating tsgo with the @typescript/native-preview package. Early experimentation delivered potential benefits like stricter type checking and faster incremental builds, but the implementation introduced compatibility issues with critical dependencies (notably mongoose Schema typings) and required temporary workarounds that increased maintenance burden. After attempting the mongoose 9.0.1 upgrade and encountering issues from having exactOptionalPropertyTypes enabled in our tsconfig, we reverted to the 8.17.0 version and now prefer to keep the existing tsc-based workflow stable while TypeScript 7 matures.
Decision Driversβ
- Future Compatibility: Monitor TypeScript 7.0 while waiting for first-party stability
- Enhanced Type Safety: Track
tsgoand@typescript/native-previewto adopt them when the benefits outweigh the costs - Performance Balance: Avoid premature optimization if it impairs the developer experience today
- Dependency Compatibility: Keep mongoose, Vitest, and other core libraries running on the officially supported TypeScript toolchain
- Stability: Roll back the mongoose 9.0.1 upgrade (migrating back to 8.17.0) because the new typings triggered exactOptionalPropertyTypes issues in our tsconfig that the tsgo build could not resolve.
Considered Optionsβ
- Adopt tsgo with @typescript/native-preview immediately
- Wait for official TypeScript 7.0 release
- Use alternative type checking tools
Decision Outcomeβ
Chosen option: "Wait for the official TypeScript 7.0 release", because the temporary compatibility workarounds (like skipLibCheck, mongoose type facades, and editor extensions) are more disruptive than the incremental benefits right now. We will continue to monitor tsgo and revisit the migration once the tooling and type definitions stabilize.
Consequencesβ
- Good, because we avoid fragile tsgo-specific workarounds across multiple packages
- Good, because we reverted the mongoose upgrade back to 8.17.0 which preserves a stable dependency while we wait for tsgo/mongoose 9.x typings to catch up
- Neutral, because we lose early access to TS7 features but gain confidence in the current compiler
- Bad, because we defer potential compilation and runtime benefits from tsgo until later
Validationβ
- We exercised
tsgo --buildacross every workspace package and hit new type errors that do not occur when runningtscwith no changes: mongoose emits aTS4109circular-reference failure (notably under packages/ocom/data-sources-mongoose-models/dist/src/index.d.ts), and our own code surfacesTS2742βinferred type cannot be namedβ errors. - The only ways we could persuade the
tsgocompiler to finish were enablingskipLibCheckeverywhere (even downstream packages that never touch mongoose) or layering temporary stub mongoose typings that hid the real errors. Neither approach felt acceptable because they amount to manual workarounds for tsgo bugs instead of a stable migration path. - Because there was no way to satisfy the CI pipeline when using
tsgowithout those temporary changes, we kept the existingtscworkflow and decided to revisittsgoonce TypeScript/mongoose typings stabilize.
More Informationβ
- Every
tsgo-specific configuration was removed:tsconfigfiles extend the base config withoutskipLibCheck, package scripts calltsc, and temporary mongoose type facades/stubs have been deleted. - The TypeScript (Native Preview) VS Code recommendation and other editor guidance were reverted to the standard experience.
- We continue to monitor TypeScript Go for resolver improvements but intend to revisit this work only once TypeScript 7.0 and the related mongoose typings (TS4109) stabilize.
pnpm run verifyremains the benchmark for verifying the migration when it is reattempted.
Future Actionsβ
- Track the TypeScript 7.0 release timeline and tsgo stability so we know when a second attempt makes sense.
- Keep an eye on mongoose typings (TS4109) to see when the schema recursion issues resolve without requiring
skipLibCheckor manual stubs. - Reassess the necessity of the
@types/chaipin whenever the Vitest globals conflict is resolved. Needed to pin@types/[email protected]in rootpackage.jsonoverrides section to avoid conflicts with Vitest-provided types when usingtsgo. - Document any follow-up migration plan before reintroducing new tooling.
Weekly Reassessmentβ
- Every Monday, review the linked issues to see if the tsgo blockers have advanced toward resolution. Update this ADR and the main README.md's In Progress ADRs section with the new status and any clean-up that becomes relevant.
- Schema circular reference (TS4109): Issue 929 (monitor the related issue 948 even though it is closed in case the problem reappears).
- Inferred type cannot be named (TS2742): Issue 2220 plus the related reports 2233 and 2277.
- tsgo issue queue: Refer to the TypeScript Go issue tracker as needed to find other relevant bugs that impact our planned migration.
Remediation plan after TypeScript 7 GAβ
- Revisit this ADR and either mark it as superseded or update it with the new migration plan.
- If tsgo proves stable, reintroduce the necessary configuration changes (plugin,
@typescript/native-preview, tsconfig tweaks) while following the previously documented steps for mongoose isolation. - Remove any remaining
skipLibCheckflags and stub type facades once the official mongoose typings can coexist with tsgo. - Unpin
@types/chaiwhen the Vitest conflict is fully fixed and the default types align with our usage. - Run
pnpm run verifyagain to prove that linting, building, testing, SonarCloud, and Snyk scans pass without requiring temporary compiler workarounds for tsgo.
Tracking tsgo progressβ
- Keep an eye on the TypeScript Go README for updates on
tsgo/@typescript/native-previewfeature parity and resolver improvements so we can reassess the temporary.jsimport extensions when relevant.