Skip to content

Proposal to support passing resolved compiler into webpack options - #1725

Closed
aovchinn wants to merge 2 commits into
TypeStrong:nextfrom
aovchinn:feat/node-16-pass-resolved-api
Closed

aovchinn wants to merge 2 commits into
TypeStrong:nextfrom
aovchinn:feat/node-16-pass-resolved-api

Conversation

@aovchinn

Copy link
Copy Markdown

#1721

this is just a PR version of the patch sent in a comment #1721 (comment)

I don't know how tests are supposed to run with different node versions, maybe supporting node16 is indeed just not worth the effort

added one "artificial" test, it passes on node 16 with npm run execution-tests -- --single-test suppliedCompiler

Comment thread README.md
| `string` | `'typescript'` |
| Type | Default Value |
| ------------------------------------------ | -------------- |
| `string \| { API, createFileSystemLayer }` | `'typescript'` |

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the documentation is correct - here; it's an object that's passed and default value is not 'typescript'?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default is typescript used here https://github.com/TypeStrong/ts-loader/pull/1725/changes/BASE..f110b488792612b481dea18cdd36fb998b123170#diff-1bded13bfea4654df3b721738a266a835230e5539fe6fd27bc822e42a01ecd6fR44

const compiler =
    typeof loaderOptions.compiler === 'object'
      ? loaderOptions.compiler
      : requireCompiler(loaderOptions.compiler ?? 'typescript');

@johnnyreilly johnnyreilly Nov 13, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's true - but it's quite peculiar!

Effectively the type is (I think):

'typescript' | 
{ 
    createFileSystemLayer: (files: RequestFileEntries, options?: CreateFileSystemOptions) => RequestFileSystem;
    API: new (options?: APIOptions) => API;
}

I think it would be better if the default was undefined and that 'typescript' | was removed from the union. Do you see what I mean?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but we can pass string like 'typescript-beta' or some other string that will be resolved in requireCompiler
maybe I am missing something

I tried to keep changes minimal, so that old configs would keep on working and only node 16 users would need to change webpack configs (pass object with API and createFileSystemLayer)

so if compiler option is missing default 'typescript' is used and required in requireCompiler

Comment thread src/types.ts
/** `API` from `typescript/sync` and `createFileSystemLayer` from `typescript/fs`. */
export interface TypeScriptCompilerModules {
API: new (options?: APIOptions) => API;
createFileSystemLayer: typeof createFileSystemLayer;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this approach work if we didn't pass createFileSystemLayer - my guess is no, but I'm curious

@johnnyreilly

Copy link
Copy Markdown
Member

Unfortunately the execution test you added can't be run on Node 16 as Node 16 is incompatible with Jasmine 7.
Let me see if I can try something

Install and build on Node 26 (Jasmine 7 and the dev tooling need it), then
switch to Node 16 for the build-only suppliedCompiler test, which never
loads Jasmine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@johnnyreilly

johnnyreilly commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

Thanks for putting this together @aovchinn!

I've added a CI job that installs and builds on Node 26, then switches to Node 16 to run suppliedCompiler. That test has no specs, so it never loads Jasmine 7, which needs a newer Node.

With TypeScript 7.1.0-beta it passes. With typescript@next (7.1.0-dev.20261113.1) it fails:

Error: Starting or connecting to a TypeScript API server requires Node.js 20.16 or later; in other environments, provide a transport.
    at nodeProcess (.../typescript/dist/api/nodeProcess.js:10:15)
    ...
    at new API (.../typescript/dist/api/sync/api.js:70:23)

(job log)

The latest TypeScript nightlies load Node built-ins through process.getBuiltinModule, which only exists in Node 20.16+. Several files in dist/api rely on it, not just nodeProcess.js. So on Node 16, new API() throws however ts-loader gets hold of API, and passing { API, createFileSystemLayer } from an ESM config doesn't get around it. (The package's engines still says >=16.20.0, but that seems to cover only the compiler, not the API.)

So Node 16 support would only work with 7.1.0-beta, and the next TypeScript 7 release would break it. The only workaround would be for ts-loader to provide its own transport to the API, or to polyfill process.getBuiltinModule.

Can you think of an approach to tackle this?

@johnnyreilly

johnnyreilly commented Nov 13, 2026 •

Copy link
Copy Markdown
Member

I think that microsoft/TypeScript#64174 stopped this PR from being viable as is.

Spawning a native tsc from the API now needs Node.js 20.16+. Passing a transport works anywhere. engines stays at 16.20 for the CLI.

@aovchinn

Copy link
Copy Markdown
Author

#1725 (comment)

yeah, in light of that new info I think it is not possible to support node 16

@aovchinn aovchinn closed this Nov 13, 2026
@johnnyreilly

Copy link
Copy Markdown
Member

well done for trying though! Before the latest changes I think this was looking quite promising

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants