16 comments

  • jauco 9 hours ago
    Newer versions of node can run typescript directly[1]. The one where types are simply stripped is considered stable[2] (but you can’t use syntax that node doesn’t understand, such as enums).

    They’re working on making features work that require some transpilation as well

    [1]: https://nodejs.org/en/learn/typescript/run-natively [2]: https://github.com/nodejs/node/pull/58643

    • eyelidlessness 7 hours ago
      Completely picking nits: Node doesn’t understand types at all, the distinction is between what TypeScript now calls “erasable syntax”[1] versus syntax excluded by that. The exclusion of enum isn’t likely to affect many projects (because enum has long been panned by most users). Same with namespace. By far the most likely incompatibility is “parameter properties”, ie class fields assigned in the constructor signature.

      1: https://www.typescriptlang.org/tsconfig/#erasableSyntaxOnly

      • veidr 3 hours ago
        This is exactly right, and the constructor parameter incompatibility is a big deal. The other two aren't nothing, either, even if enums are generally not the prevailing best practice in most cases.

        This is an interesting development, but it's not really "running TypeScript code" its "almost running TypeScript code".

        With alternative runtimes like Deno and Bun able to run real TypeScript code (and type check it, lint it, test it, etc) using a slightly watered-down, not-fully-compatible dialect of TypeScript, just so that it can run on Node without a build step, really isn't a very compelling argument.

        It'd be different if TypeScript announced "TypeScript will remove these features to work around Node's limitation — compatibility is more important", but they haven't.

        (And I wouldn't personally love it if they did. Deno and Bun are ahead of Node on several different axes, and other runtimes are coming, too — if Node can catch up, then great, but if it can't, then it should rightly be left behind.)

        There's still no real alternative to Node for many large frontend apps in production, but for a lot of other TypeScript use cases — build tooling, backend APIs, CLI apps, edge functions — modern TypeScript in the Deno/Bun style (ESM, full filename imports, run/typecheck/lint/test with no user-configured build step) has significant benefits.

        Both Deno and Bun have extensive — and necessary — backward compatibility shims to enable interoperability with what I've started calling "legacy Node JS/TS". You can use the Node APIs (but should explicitly import those things with "node:" in your import specifier. You can use NPM packages (even CommonJS ones, although Deno prohibits CommonJS in new code, a stricter line than Bun draws).

        I don't think using Deno and Bun is a huge bet on those specific (VC-backed) runtimes, either, because there is a shared vision of what "modern TypeScript" looks like, it works with both of those tools, and I think there will be multiple runtimes that support that vision for as long as TypeScript is relevant, even if both Deno and Bun were to go sideways.

        Whether Node itself will become one of those modern runtimes is an interesting question. This is a step in that direction, it looks like, but it's still an open question.

      • alpinisme 7 hours ago
        Some people hate enums but they’re the only easy form of nominal typing in typescript, and for that alone you can pry them from my cold dead hands.
        • matt_kantor 5 hours ago
          I find that for most of my use cases, branded types[1] are close enough to nominal (especially if you use a private `unique symbol` as the brand).

          [1]: https://www.learningtypescript.com/articles/branded-types

        • eyelidlessness 7 hours ago
          I agree completely. But I also know I’m in the extreme minority. Now I just use erasable syntax even on my personal projects because it’s less friction. Maybe someday the enum proposal in TC39 will mix this up a bit!
        • rictic 3 hours ago
          Private fields, unique symbols, there's many ways to do nominal typing in TypeScript, depending on what you want.
        • goodoldneon 5 hours ago
          Why is nominal typing desirable?
      • nsonha 4 hours ago
        > enum has long been panned by most users). Same with namespace

        Why? Would you would rather do a smurf naming convention than having your consts, DTOs, events, errors and what not neatly organized under the name of the function that uses it?

    • ethan_smith 3 hours ago
      The --experimental-strip-types flag is actually stable in Node.js 22 (released May 2024), so you can run TypeScript directly with `node --strip-types file.ts` without the experimental prefix. This makes Node's native TypeScript support even more practical for everyday use.
    • theThree 3 hours ago
      It still have issues. Example: `import foo from "./Foo"` doesn't work. You have to `import foo from "./Foo.ts"`
  • chmod775 9 hours ago
    That's some terrible naming. Now there's two things "tsx" stands for in the TypeScript ecosystem.
    • VPenkov 8 hours ago
      Been using tsx for years. This had never occurred to me, but you're right
      • conradkay 3 hours ago
        It took me a couple seconds to figure out what they even meant (.tsx for React) so it's probably not really a bad name.
    • subarctic 8 hours ago
      Yup. But it's useful so I use it
  • low_tech_punk 7 hours ago
    To make matters worse, there is actually a third thing named "TSX" gaining traction right now:

    https://esm.sh/#tsx

  • low_tech_punk 7 hours ago
    I don't think it's accurate to say "without worrying about configuration". The next line is more accurate:

    > tsx runs your TypeScript code with modern and sensible defaults, making it user-friendly and especially great for beginners.

    You'd still have to worry about config if you want to make adjustment and when that happens, the implicit smart defaults become a friction point.

    It might also surprise you with errors when you attempt to bundle the code. It'd be nice to have tsx available at runtime so I can run TypeScript code without worrying about the transpiler

    • nailer 7 hours ago
      > You'd still have to worry about config if you want to make adjustment and when that happens, the implicit smart defaults become a friction point.

      In practice (when using tsx and when using a similar prececessor tech, esrun) ES moves forwards, not backwards.

      Is your target "supported node.js and current browsers"? Today's tsx defaults work with that. They'll also work with tomorrows node.js and current browsers.

      • keysdev 7 hours ago
        esno seems a better alternative. esbulit has already solve much of that for devs.
        • Quarrel 5 hours ago
          esno is now tsx, from their github:

          > From v0.15, esno is essentially an alias of tsx, with automated CJS/ESM mode and caching.

          and all issues are now filed in the tsx repo.

  • dimgl 6 hours ago
    tsx is such an amazing tool. A couple of years ago I discovered it and abandoned ts-node and all of the alternatives. I still use it today and I was a sponsor for many months.

    Thanks again to the author. It has saved me (and my team) dozens of hours. And I was able to replace all of my ESBuild workarounds that I had made to easily run TypeScript. Cheers.

  • hu3 8 hours ago
    I was curious about how it works.

    It seems to be a wrapper for esbuild that transpiles typescript then calls your local node (it doesn't bundle nodejs).

    From https://tsx.is/faq :

    "tsx: Uses esbuild for fast compilation and does not perform type checking."

    From https://tsx.is/node-enhancement :

    "Under the hood, tsx calls node. This means the Node.js features supported in tsx depend on the Node.js version you have installed."

  • fjcero 9 hours ago
    Use bun
    • dimgl 6 hours ago
      Bun is still unstable for me. I’ve had to switch back to Node for several projects and I end up falling back to tsx.
    • daveidol 1 hour ago
      Or deno
    • danscan 8 hours ago
      Came here to say this :)
  • spankalee 9 hours ago
    Does this just pass the --experimental-strip-types flag to node?
    • webstrand 9 hours ago
      Last I knew, it did the transpilation itself so that it could handle module path resolution manually.
      • basetensucks 9 hours ago
        It does more, it also includes a compatibility layer allowing you to require ESM packages in CJS. It's quite handy!
        • andrus 9 hours ago
          Don’t recent Node.js releases support this already? require(esm) was back ported to Node.js 20 in February
    • joshuaturner 8 hours ago
      With node24, no flag needed. These tools are really great and I'm happy to see improvement in the space, but I'm even happier to be able to start getting rid of them with native node improvements.
  • cellis 7 hours ago
    It really is the worst name, unsearchable and so overloaded. But it's been an awesome tool. I hope they rename it.
  • gosukiwi 7 hours ago
    TypeScript is great, the only bad thing is that it can be a pain to get the configuration right
  • postalrat 9 hours ago
    The JavaScript version can be called jsx.
    • cacozen 9 hours ago
      The HTML version can be called HTMX
      • SwiftyBug 8 hours ago
        The Java SE version can be called Java SEX.
  • lacoolj 8 hours ago
    lol the timing of these two posts (this and https://news.ycombinator.com/item?id=44597966) feel deliberate
  • molszanski 9 hours ago
    I love tsx. Lately I’ve been also using bun for the same purpose.
  • 90s_dev 3 hours ago
    Note that you can also get TSX in native Node.js with minimal configuration[0]. This is accomplished via module hooks and TypeScript's own compiler (or bring your own compiler like swc).

    [0]: https://github.com/sdegutis/immaculata

  • monarchwadia 10 hours ago
    I do love tsx.
  • neeelrusia 9 hours ago
    [dead]