-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
Transpile TypeScript code inside node_modules
.
#58429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I don’t think there’s any reliable way to ensure people don’t publish untranspiled code except never having this feature by default - people will find workarounds if they need to. Postinstall scripts can add private true, or use symlinks, or make any change that would distinguish - it’s just not an achievable guarantee. |
That same argument applies to publishing untranspiled TypeScript to npm today, there’s nothing preventing someone from doing it now, even without this feature. While npm may have become a de facto standard and can enforce certain norms within its ecosystem, Node.js itself cannot (and arguably should not) enforce the same rules across all private or self-hosted registries. In short, preventing misuse entirely isn’t a realistic goal. Instead, Node.js should aim to enable powerful, ergonomic workflows for legitimate use cases, like monorepos, while still discouraging misuse through clear defaults and documentation. |
FYI this was already suggested (and rejected) in #57215. |
Hm. #57215 links to #55385, which says
But this thread implies that packages that resolve via a symlink in node_modules to something outside node_modules are not being transformed, contrary to my understanding of the above comment. What's the intended behavior for that case? |
I have a monorepo that supports both
{
"exports": {
"import": "index.js",
"importts": "index.ts"
}
}
Is it pretty? No.
Given the above, I don't think this is true 🙈 |
@slagiewka that's quite interesting... I wasn't aware this was possible at all. I wonder if Node's maintainers were also aware of it or if they will take any actions against it. If this is possible today, why not just document this interesting behavior as something like: {
"exports": {
"import": "index.js",
"typescript": "index.ts"
}
}
|
This use case is documented in Amaro |
FWIW this condition based approach was what we had recommended previously; prior art is: |
That being said, I'm not sure why the realpath-ing is not working in this case, unless I'm not understanding the problem. Would need a real repo for an example. |
It's not bypassing the |
Node.js: developers are discouraged to upload TypeScript to npmjs.com. But, npmjs.com: developers are free to upload their favorite movies. The Actually If a library's downstream developers really want TypeScript code, re-transpiled with their favorite bundler, then the library's developer does have reason to upload TypeScript to npmjs.com. I also don't understand why Node.js insists on this limitation. |
You say that when you just gave an example of why we cannot assume we'd be able to transpile |
Uh oh!
There was an error while loading. Please reload this page.
What is the problem this feature will solve?
I do not propose allowing transforms for all packages in
node_modules
. That would encourage publishing TypeScript directly to npm, which comes with significant downsides for the ecosystem.With the introduction of
--experimental-strip-types
and--experimental-transform-types
, it is now feasible to run TypeScript code directly without a separate build step.However, in monorepo environments, this feature is limited by how Node.js currently handles
node_modules
resolution. In a typical monorepo setup, you might have a structure like:Tools like
pnpm
(and similarlyyarn
andnpm
workspaces) install local packages via symlinks into thenode_modules
folder. For example, ifserver
depends onlibA
,pnpm
will symlink (or copy, depending on configuration)libA
intoserver/node_modules/libA
.The issue is that Node.js currently does not apply
--experimental-strip-types
or--experimental-transform-types
to anything inside anode_modules
folder, even if it’s a symlink to a local workspace package.This forces developers to pre-transpile any local dependencies, which essentially defeats the purpose of the feature in monorepos, where the
server
package often represents only a small percentage of the codebase compared to its locally installed dependencies.This might introduce some complexity to the current implementation, since each package could have its own
tsconfig.json
with potentially different options. That said, I’m not deeply familiar with the internals of--experimental-strip-types
and--experimental-transform-types
, so this is just an assumption.Bun and Deno come to mind as the major runtimes that support TypeScript out of the box. A study might be needed to determine how to handle
tsconfig
resolution when transpiling packages insidenode_modules
. Should it respect each subpackage's owntsconfig
? Or should it transpile everything according to theserver
’stsconfig
? I’m also unsure what the best or most correct approach would be here.What is the feature you are proposing to solve the problem?
I'm still unsure what the best decision would be here, as there are multiple ways to distinguish which folders inside
node_modules
come from local/owned packages and which do not. What about private registries? There's still a lot to decide.What alternatives have you considered?
Some options have come to mind:
node_modules
that have"private": true
. This ensures those packages did not come from a public registry.--transpile-packages=@mycompany/*
to explicitly opt into transforming specific scoped packages."source": "./src/index.ts"
or a custom flag such as"needsTranspilation": true
.A flag like the latter would be especially useful, as it would enable users to publish TypeScript packages to private or internal registries while still opting into transformation behavior.
Since this restriction was intentionally designed to prevent publishing uncompiled TypeScript to npm, perhaps a more consistent approach would be to only block transpilation for packages that clearly come from the public registry. Again, there's a lot to discuss here...
The text was updated successfully, but these errors were encountered: