-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
How could we support typescript without vendoring it? #43818
Comments
cc @cspotcode |
So basically you would like Node.js to automatically load something from a global predefined place when it starts? |
Yes, but only when started with a |
Wasn't that the main purpose of custom loaders? You should even be able to set that in a |
Please don't start issues related to loaders without tagging @nodejs/loaders |
This is not related to loaders. This is about the developer experience of Node.js. Please keep this issue about the user experience and not specific implementations. |
I'm trying to see how this isn't reinventing the wheel, but I'm not getting it. Could you please explain how it's substantially different? How I'm seeing it is: This is already easily achieved via Loaders with next to no effort (and that effort is basically set-and-forget). We have a simple working example of it in PS In case we veer into the territory: I would vehemently object to TypeScript support in Node itself. |
I would rather stay away from discussing a specific implementation of this. This could be loaders but it doesn't matter. I care about listening to our users. Once we agree on the user experience, then we figure out what's the best way to ship it. If it's already possible as you hinted, it would be terrific.
That's what our users are asking for. We cannot provide TS directly into Node.js core for plenty of reasons (it's just not possible for the tsconfig mayhem), including the fact that the TS team think it's a bad idea. I propose that we implement the user experience described in #43818 (comment). |
A few questions come to mind:
Currently, what happens when someone runs
We would then need a way to detect that |
In an app with node script.ts
node:internal/errors:477
ErrorCaptureStackTrace(err);
^
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /private/tmp/test/script.ts
at new NodeError (node:internal/errors:388:5)
at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:80:11)
at defaultGetFormat (node:internal/modules/esm/get_format:122:38)
at defaultLoad (node:internal/modules/esm/load:21:20)
at ESMLoader.load (node:internal/modules/esm/loader:431:26)
at ESMLoader.moduleProvider (node:internal/modules/esm/loader:350:22)
at new ModuleJob (node:internal/modules/esm/module_job:66:26)
at #createModuleJob (node:internal/modules/esm/loader:369:17)
at ESMLoader.getModuleJob (node:internal/modules/esm/loader:328:34)
at async Promise.all (index 0) {
code: 'ERR_UNKNOWN_FILE_EXTENSION'
} So to provide the UX you’re describing, we would have to add a special case within this error flow where if the unknown extension is In an app without Either way, the solution that we would be recommending to users would involve adding the TypeScript loader. And transpiling TypeScript is squarely one of the use cases for loaders. So I object to treating this as “not related to loaders” and removing that label. |
@GeoffreyBooth let's imagine that the solution ends up looking like that (oversimplification): if (entryPoint.endsWith('.ts')) {
process.argv.unshift(entryPoint);
entryPoint = '~/.node/typescript-node-core/bin.js';
} Sure |
What if it were some kind of…plugin (idk what the official term is relative to Node.js), like crypto or intl, with which node could be compiled or not? We could then have however many and we aren't responsible for them. It would be very similar to loaders, but a bit different and i think perhaps a little closer to what Matteo is talking about. Also, this would avoid incorporating typescript-specifics (eg their .ts vs .js file extension nonsense) into node core (which is my main concern). Annnnd it wouldn't require the CLI args everyone laments about loaders. |
Yeah, I think the important factor is user experience. Not sure how loaders work exactly but a DX like this would work - it could be specified in a configuration file which loader to use given an extension:
This could have global defaults and local (package.json) overrides. The global defaults would be shipped with node.js. Maybe cli flags could be passed to the loaders, when needed. This way we can load any file conveniently with |
One thing to keep in mind: ...but that's a detail. High-level ask from users is still: "How do I opt-in to my runtime having automatic TS support?" |
When we say that users are asking for TS support, is there a sense for the ratio of desire for TS support vs desire for <insert non-TS thing here>? |
I am in favor of this and I think we are not doing a good enough job. I like Matteo's proposed idea of a blessed "how to run TypeScript module" - ideally I'd also like us to provide a We'd probably need:
Might also be interesting to know if this unlocks optimizations? |
The sense in general as well as the trend from every other runtime is: Users are asking for better TypeScript experience a lot and almost no users asking for other type systems (like flow) or languages (like reason). Heck, someone opened an issue on this today |
Also let me try pinging some TypeScript people |
Not at this point. I would be happy to evaluate other languages (like coffeescript), but I do not think any other language is as popular as TypeScript. Anyway, I think our implementation should allow for more extensions to be considered for inclusion. |
More radical: bundle swc and just run the code. :-) (Caveat emptor: swc is a transpiler, not a type checker. But on the flip side, it also handles JSX and TSX.) |
That's not so crazy to me. It's sort of what I was suggesting above: #43818 (comment) |
After seeing how other emerging runtimes provide native TypeScript transpilation by default, I am in favor of @mcollina's proposed idea. I'd like to see Node support running TypeScript code, ideally out of the box, with no additional flags or options. |
I'm in favor of @orta proposal. I have some questions:
Why? I don't see why this would be needed.
We should provide some configurability for this mechanism, something in |
I assumed that because they were called ESM module loaders they would be ESM only - but if not, that makes a stronger case for this technique. The configurability makes sense, as "typescript" would be default any other loader-ish package definition should be able to overwrite it 👍🏻 |
I think there is a plan / possibility to extend them to CJS too. |
Hi @orta, thanks for your ideas. A few thoughts:
Loaders are on the verge of being stable: https://github.com/nodejs/loaders#milestone-1-parity-with-commonjs. Adding support for some type of file-based configuration (as opposed to the current flag-based) is on the roadmap, but unnecessary for the Loaders API to leave experimental status because it shouldn’t be a breaking change to add a new way of defining configuration. There are no API changes needed to support TypeScript, as it works today via things like Also, a solution along these lines, where we don’t special-case the |
This is a bit misleading since |
I’m unsure what this means. We’re not intending to change Node to break TypeScript support. On the contrary, making the Loaders API stable is meant to achieve the opposite: an API that can be relied upon, that won’t be removed or changed absent a Node semver-major change. We have discussed adding similar customization APIs for things like source maps and the REPL and so on; I assume these are the “non-loader hooks” you refer to? The goal there would be to add APIs to allow tools like |
We have to use undocumented monkey-patches. When node ships breaking changes to undocumented monkey-patchable functions -- perhaps accidentally -- there is sometimes resistance to fixing the breakage, since the API surface is undocumented. Stabilizing loaders is good, but it doesn't stabilize these undocumented hooks. From a maintainer's perspective, this risk is not fun. One of those hooks is to give us proper module resolution: I agree everyone's on-board to enable great TS support. I hope that until the loaders API fully supports the necessary hooks, the node team will treat these undocumented monkey-patches as an API surface that cannot be broken. |
The undocumented hooks you’re talking about are additional scope beyond the Loaders API, but something we intend to address with a new Customization API: nodejs/loaders#95. The goal is to support things like |
These days it is common to use services that do provisioning and management for you, AWS Lambda in particular. So they do not care that much about node.js runtime. Secondly, I can't believe external transpilation could do better than native execution. Thirdly, bun and deno already have this feature. Their runtimes want to stand out and get some audience based on unsolved needs. Isn't it a good sign that market expects TypeScript to be there? |
I think we can have pre-defined values of tsconfig and the developer who wants to use other resources create inside the folder manually. |
Ok, I started to experiment with implementation and here are my findings/opinions for tonight:
then
if the
I won't have coding time for a couple days, but should go back into writing stuff early next week |
@vdeturckheim This looks good! A few thoughts:
|
Thanks @GeoffreyBooth , these are very good points! Regarding node vs. package version, this is a very good point. For repl and I missed last summer's summit (and this thread until recently fwiw), so I hope I am still going in the direction people agreed upon 👼 |
Yes, I think nothing has changed from #43818 (comment) and what your recent experiments seem to assume. About the only “news” is that we’ve made so much progress with the Loaders API that I can see it applying to CommonJS too in the not-too-distant future; so I would prioritize getting TypeScript support via Loaders working first or at least ship that at the same time as CommonJS solution. @cspotcode and others have also had discussions about hooks in addition to those provided in the Loaders API, to do things like customize the REPL, for a more seamless DX beyond loading modules. Hopefully we can use the interest in better TypeScript support to build out some of those APIs. It sounds like |
This sounds good, thanks for the highlights! Seems good to me! I'll resume work with that in mind! Regarding the point in not treating But let's focus on the MVP for now and add too much complexity later 👼 |
+1 on this ^^ |
I’m not sure Node needs to publish a transpiler at all. Whatever docs page our error message links to could include a list of ones known to work, and encourage the user to choose one to install. I would think we should at least start with that approach, and if we find a need for publishing something official we could do that after MVP. |
This comment was marked as off-topic.
This comment was marked as off-topic.
There is a related proposal to add type syntax to JS, checkout: |
What is the latest update on this? With both Deno and Bun improving their compatibility with Node.js and providing native support for TypeScript, there seem to be numerous examples and lessons to be learned from their advancements. Since it hasn't been mentioned in this thread, I would like to inquire whether this proposal could enable the distribution of npm packages exclusively written in TypeScript. Such a capability would significantly enhance the user experience when working with Node.js and TypeScript, eliminating the need to juggle between .d.ts and .js files. |
We’re exploring this space via #49704 (cc @JakobJingleheimer). One idea we’ve been considering lately is that Node could possibly provide some kind of blessed or automated way to install plugins, one of which could be TypeScript. Part of the problem is that TypeScript itself doesn’t provide Node integration, and there are many third-party plugins for that purpose, and we would want to avoid picking a winner. There’s also no one correct way to set up TypeScript; it depends on your build tool and its configuration, your app and its framework and those expectations, and so on. You might want to open an issue with the TypeScript team, if there isn’t one there already. They’re the ones who have the power to add official support for runtime transpilation and/or type-checking, and/or provide a blessed/recommended |
I would like Node.js to support the following user experience
$ node script.ts Typescript support is missing, install it with: npm i --location=global typescript-node-core $ npm i --location=global typescript-node-core ... $ node script.ts "Hello World"
(I picked the typescript-node-core name at random, I would be extremely happy if that could be ts-node)
Note that
script.ts
could evaluate to either cjs or mjs depending on thetsconfig.json
file.Originally posted by @mcollina in #43408 (comment)
Why vendoring is not an option?
tsconfig
given the 100+ options.The text was updated successfully, but these errors were encountered: