feat(build): compile with the TypeScript 7 native compiler - #11793
Open
raymondfeng wants to merge 2 commits into
Open
raymondfeng wants to merge 2 commits into
raymondfeng wants to merge 2 commits into
Conversation
Install TypeScript side by side, as recommended for TypeScript 7: `typescript` is aliased to `@typescript/typescript6` so that tools consuming the JS compiler API keep working, and `@typescript/native` provides the native compiler that `lb-tsc` runs. A cold build of the monorepo drops from ~10.7s to ~2.1s. `lb-tsc` prefers the native compiler and falls back to `typescript/lib/tsc` when `@typescript/native` is not installed. TypeScript 6/7 changes that required source updates: - `moduleResolution: node` (node10) was removed. It is dropped from `tsconfig.common.json` and from the CLI project template. The default resolver for `module: commonjs` honors `exports` maps, so `@loopback/graphql` no longer imports `Middleware` from a deep `type-graphql` path and declares it instead. - `@types/*` packages are no longer included automatically, so `tsconfig.common.json` now lists `types: ["node", "mocha"]`. - Reading a parent class field through `super` is an error (TS2855), so `@loopback/cron` calls `fireOnTick` through `BaseCronJob.prototype`. - Declaration emit no longer adds `/// <reference path>` for ambient files, so `@loopback/testlab` exports the should.js types from a module rather than a global declaration file. Without it, `expect` resolves to `any` in every consuming package and api-extractor cannot follow the `Internal` symbol. `@typescript-eslint` is upgraded to v8, v7 does not support TypeScript 6. Rules that v8 renamed or split are disabled to keep the rule set this configuration already had, and the remaining new findings are fixed. Two defects surfaced by the stricter compiler are fixed as well: `belongs-to-repository-factory.unit.ts` never assigned `companyRepo` and clobbered `customerRepo` instead, and `rest.application.ts` declared the same `route()` overload twice. BREAKING CHANGE: `@loopback/build` compiles with TypeScript 7 when `@typescript/native` is installed and with TypeScript 6 otherwise. Projects extending `@loopback/build/config/tsconfig.common.json` have to remove `moduleResolution: node` and list ambient type packages in `types`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Raymond Feng <enjoyjava@gmail.com>
raymondfeng
requested review from
achrinza,
dhmlau,
marioestradarosa,
mschnee,
nabdelgadir,
nflaig and
samarpanB
as code owners
September 16, 2026 02:01
…n redirect Registered apps and issued tokens were held in plain objects keyed by values taken from the request, so a `__proto__` key reached `Object.prototype`. They are `Map`s now, which also drops the `[key: string]: any` index signature from the `App` interface (CodeQL js/prototype-polluting-assignment). `redirect_uri` is validated before redirecting and the callback url is built from the parsed `URL` rather than by concatenating the request value. A real authorization server matches `redirect_uri` against the callback urls registered for the client; this provider only ever serves test applications running on the same machine, so it accepts loopback hosts (CodeQL js/server-side-unvalidated-url-redirection). Both findings predate the TypeScript 7 upgrade - they were reported on this pull request only because wrapping the handlers re-indented the lines. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Raymond Feng <enjoyjava@gmail.com>
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.
Upgrades the monorepo to TypeScript 7, using the side-by-side install recommended
for TypeScript 7:
TypeScript 7 no longer ships the JS compiler API — its
exports["."]resolves tolib/version.cjs— so anything that introspects the compiler (@typescript-eslint,editor language services,
tsserver) needs the API that@typescript/typescript6still provides. The two packages declare different bin names (
tscvstsc6), sothey coexist with no collision.
packages/build/package.jsonis the source of truth;bin/sync-dev-depspropagatesthe spec to every workspace package, and
bin/update-template-depscarries it intothe
lb4scaffolding templates.lb-tscprefers the native compiler and falls backto
typescript/lib/tscwhen@typescript/nativeis absent, so downstream apps getthe faster build without a hard requirement on TypeScript 7.
A cold build of the monorepo drops from ~10.7s to ~2.1s.
TypeScript 6/7 changes that required source updates
moduleResolution: node(node10) was removed. Dropped fromtsconfig.common.jsonand from the CLI project template. The default resolver formodule: commonjshonorsexportsmaps, so@loopback/graphqlno longer importsMiddlewarefrom a deeptype-graphqlpath (that path is not exported) anddeclares the type itself.
@types/*packages are no longer auto-included. This accounted for 5630 of the5668 initial errors (
describe,process,NodeJSall unresolved);tsconfig.common.jsonnow liststypes: ["node", "mocha"].superis an error (TS2855).crondeclares
fireOnTickas a field but installs it on the prototype, so@loopback/cronnow calls throughBaseCronJob.prototype./// <reference path>for ambient files.TypeScript 5.2 emitted one into
testlab/dist/expect.d.ts, which is how consumersresolved the global
Internaltype. Without it,expectsilently becomesanyinevery consuming package and api-extractor fails with
Unable to follow symbol for "Internal".should-as-function.d.tstherefore movesto
src/should-as-function.tsand exports its types as a module.Lint
@typescript-eslintmoves to v8 — v7 caps attypescript <5.6.0and does not supportTypeScript 6. Rules that v8 renamed or split are disabled to preserve the rule set this
config already had (
no-var-requires→no-require-imports,ban-types→ its threesuccessors); that covered 1135 of 1232 findings. The remaining 97 are fixed in code.
v8's
no-misused-promisesalso crashed oncli-main.js, which used a top-levelCommonJS
return— the rule assumes everyreturnhas an enclosing function. That isrestructured as if/else.
Defects found along the way
belongs-to-repository-factory.unit.tsnever assignedcompanyRepo; its stub helperassigned
customerRepotwice, clobbering the previousbeforeEach.rest.application.tsdeclared the sameroute(verb, path, spec, handler)overloadtwice.
lb4 appgeneratedprocess.env.HOST || '127.0.0.1', so every newly scaffolded appfailed its own
npm run lint. The adjacentPORTline already used??.bin/sync-dev-deps.jshad been broken since the Lerna → npm workspaces migration(d5c4994 removed
loadLernaRepo); repaired with the@npmcli/map-workspacespattern already used by
update-template-deps.js, since propagating the new specdepends on it.
Behavior notes
The
||→??conversions touch framework code. No boolean operand was converted, sofalse ?? truecannot bite. Two numeric operands now honor0:examples/rpc-server(port: 0means an ephemeral port) andhttp-caching-proxy(
error.statusCode). Nine string sites now honor an explicit''. The rest are arraysand are equivalent.
Verification
npm run lintdocs/apidocsoutput byte-identicalnpm ci+check-package-metadatalb4 appPre-existing and unrelated:
packages/cli/test/**generator tests time out locally(CI does not run that glob), and
packages/cli/.yo-rc.jsonis stale —--metaregenerates 126 lines of difference with or without this change.
Checklist
npm testpasses on your machinepackages/cliwere updatedexamples/*were updated🤖 Generated with Claude Code