[HN Gopher] Node.js adds experimental support for TypeScript
       ___________________________________________________________________
        
       Node.js adds experimental support for TypeScript
        
       Author : magnio
       Score  : 981 points
       Date   : 2024-07-25 02:57 UTC (20 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | me_vinayakakv wrote:
       | Nice to see Node.js getting parity on this with Deno and Bun
        
         | Klaster_1 wrote:
         | This reminds me of io.js situation, where in the end major fork
         | changes were incorporated into Node. This is why I am
         | comfortable staying with Node and npm for my projects - the
         | features will eventually trickle down anyway.
        
           | ibash wrote:
           | But in the meantime you suffer for it.
           | 
           | How many days have you spent on webpack config? Or the
           | package.json type property? Or yarn/pnpm/etc particulars?
           | 
           | I have spent too many.
           | 
           | Bun is quite nice.
        
             | Klaster_1 wrote:
             | Very true, rising popularity of deno and bun clearly
             | indicate that new runtimes solve real issues people have.
             | That's why I mentioned "my projects", your experience may
             | vary.
        
             | crabmusket wrote:
             | Is Bun's bundler on par with webpack for features? You
             | can't escape webpack* if you're targeting frontend.
             | 
             | *Or vite, or whatever equivalent.
        
               | iainmerrick wrote:
               | Using vite _is_ escaping webpack!
        
           | devjab wrote:
           | This is the "enterprise" approach and it's a solid one in my
           | book. I do think drop-ins like Bun and PNPM are always great,
           | however, and we've adopted both where it has made sense. I
           | don't think Bun will make sense very often as it's only when
           | you really need the performance the added maintenance becomes
           | worth it. Especially right now where it's not exactly stable
           | for a lot of things. PNPM however is often very great
           | compared to NPM and doesn't add much maintenance as the
           | tooling essentially gives your developers a very similar
           | experience.
           | 
           | I'm also not sure the features will eventually "tickle down".
           | I'm not sure NPM wants to adopt the advantages PNPM gives you
           | as an example, and it's probably a good thing too considering
           | the basis of NPM is just a really solid system to build on
           | top of which it wouldn't be if it was very opinionated. One
           | of the big issues Node has today is that it was very
           | opinionated with CommonJS, which made sense at the time, but
           | is a ginormous pain in the butt in the modern world. Though
           | the blame is obviously not with Node alone.
        
         | theflyinghorse wrote:
         | On the topic of typescript - yes. However Bun has a lot more
         | tools baked in than Node does at (bun test for instance). Would
         | be real nice to see Node start adopting more ideas from Bun and
         | others.
        
           | iecheruo wrote:
           | Give node a closer look, it's been quietly accruing those
           | features.
           | 
           | node has a built in test runner now
           | 
           | https://nodejs.org/api/test.html
        
           | joshmanders wrote:
           | I find it interesting that everyone looks at Bun and shames
           | Node saying they need to catch up to Bun and implement stuff
           | Bun has but Node doesn't, yet nobody is like Bun should catch
           | up with feature parity of Node. Node isn't trying to replace
           | Bun, Bun is trying to replace Node so it should be the one
           | who needs to match parity.
        
             | pfg_ wrote:
             | Bun is doing that - every update usually has node compat
             | fixes or improvements and the list of supported modules has
             | gone up significantly since it was released
        
       | vithalreddy wrote:
       | Simply amazing!
       | 
       | I wonder bun and deno support for typescript played a big role
       | here :)
        
         | yamumsahoe wrote:
         | i do wish nodejs adopts uwebsockets (totally what makes bun
         | fast)
        
           | WuxiFingerHold wrote:
           | Yes, many aren't aware of that. If nodes webserver
           | performance is not enough, you could always use uwebsocktsjs
           | or hyperexpress with node.
        
         | matrixhelix wrote:
         | This is why competition is important
        
       | rockwotj wrote:
       | My favorite deno feature is coming to node directly. Awesome!
       | 
       | Maybe this means I don't always have to install esbuild to strip
       | types - very excited how this will make writing scripts in
       | TypeScript that much easier to use. I lately have been prefering
       | Python for one off scripts, but I do think personally TypeScript
       | > Python wrt types. And larger scripts really benefit from types
       | especially when looking at them again after a few months.
        
         | yamumsahoe wrote:
         | correction: the only deno future that i want
        
           | sholladay wrote:
           | Deno has so many other great features. Most web standard APIs
           | are available in Deno, for example. It can do URL imports. It
           | has a built in linter, formatter, and test framework. Built
           | in documentation generator. A much better built in web
           | server.
           | 
           | Node is copying many of these features to varying degrees of
           | success. But Deno is evolving, too.
        
             | johnny22 wrote:
             | the url imports is one the things I don't want.
        
               | niklasmtj wrote:
               | There are also the `npm:`, `node:` and `jsr:` specifiers
               | now. So you _don 't_ have to use the URL imports if you
               | don't feel them.
        
               | sholladay wrote:
               | You want to be forced to use a centralized registry? I
               | don't know. URL imports also enable fully isomorphic
               | modules. I think you would enjoy the freedom of URL
               | imports if the ergonomics were better. For example, it
               | should just default to https:// so you don't have to type
               | that. Import maps also help a lot with this, definitely
               | use them. But they could be even better by having first-
               | class support for templating the module version into the
               | URL so that the version can be stored separately,
               | alongside the module name. Popular hosts with well-known
               | URL structures could have their URLs automatically
               | templated so you only have to specify the host and not
               | the rest of the URL.
               | 
               | In other words, the tooling could be better, but the
               | fundamentals of URL imports are sound, IMO.
        
               | zzo38computer wrote:
               | I disagree. It should not default to "https://" (I think
               | defaulting to local files would be better).
               | 
               | Furthermore, I think that it should be made so that the
               | "hashed:" scheme that I had invented (in the Scorpion
               | protocol/file-format specification document, although
               | this scheme can be used independently of that) can also
               | be usable.
               | 
               | And, popular hosts with well-known URL structures
               | automatically templating also I would disagree, although
               | it might do to allow any expressions in place of the
               | string literals and then add functions for abbreviations
               | of some of those URLs, if that would help (although I
               | still think it is unnecessary).
        
             | throwitaway1123 wrote:
             | Node supports URL imports via the --experimental-network-
             | imports command line option. There's also a built in test
             | runner now.
        
           | WuxiFingerHold wrote:
           | ... and obviously the only one you know.
           | 
           | Kidding aside: You should really take an hour and check out
           | the manual and std lib (https://jsr.io/@std). I was surprised
           | how far Deno has come. A lot of pretty useful stuff you would
           | otherwise need tons of NPM modules for.
        
         | yamumsahoe wrote:
         | btw if anyone is looking to run ts on node, there is tsx. there
         | is also ts-node but i prefer tsx.
         | 
         | https://github.com/privatenumber/tsx
        
           | jessym wrote:
           | I second this. The tsx library is zero config and always
           | "just works" in my experience, which puts it miles ahead of
           | ts-node, imo.
        
           | iansinnott wrote:
           | Seconded again. While tsx usually just works ts-node almost
           | never just works. tsx is perhaps unfortunately named though
           | so it may confuse people at first since it has nothing to do
           | with jsx syntax.
        
             | jimvdv wrote:
             | Thank you for bringing this up, I almost ignored this
             | project since I assumed it had something to do with
             | TypeScript + JSX.
             | 
             | The JS ecosystem sure struggles with naming things.
        
               | tommica wrote:
               | The _programming_ ecosystem sure struggles with naming
               | things.
        
               | jimvdv wrote:
               | Fair enough
        
               | nikeee wrote:
               | I own the npm package node-ts, which has thousands of
               | installs per week just because people confuse it with ts-
               | node.
               | 
               | I didn't intend to typo-squat. Actually, my package is
               | older than ts-node and was just a pun because it is an
               | API for TeamSpeak written in TypeScript.
        
             | tills13 wrote:
             | It's named as such to mirror `npx`
        
           | silverwind wrote:
           | tsx has very slow startup performance, I prefer
           | https://github.com/swc-project/swc-node which is around twice
           | as fast.
        
             | herpdyderp wrote:
             | Does swc-node work with code coverage calculation
             | libraries? For a long time tsx didn't (and it's still
             | pretty finicky) so that kept me from using it.
        
               | silverwind wrote:
               | Not sure what features those need, but at least the stack
               | traces are correct in swc-node, so maybe worth a try.
        
             | dimgl wrote:
             | We have not seen this whatsoever. How big is your project?
             | `tsx` is almost instantaneous in a server-side project of
             | ours.
        
           | wruza wrote:
           | Tsx's only reset-in-console mode is <Enter>, which makes it
           | impossible to develop cli apps in watch mode.
           | 
           | You cannot run tsx from a non-project cwd if you're using
           | tsconfig/paths.
           | 
           | And personally I find its maintainers relatively unpleasant
           | to message with. Leaves "you're plebs" aftertaste most of the
           | times.
        
         | medv wrote:
         | Have you tried https://github.com/google/zx?
        
           | tnzk wrote:
           | This seems very interesting approach to scripting. Does it
           | basically provides with an alias to child_process.exec as $
           | and besides that I can write in the same way I'd do in Node?
           | 
           | > Node.js standard library requires additional hassle before
           | using
           | 
           | I read the hassle as having to setup Node runtime in advance,
           | but zx requires npm to install so I'm not sure.
        
       | deanc wrote:
       | So how does this work in practice? Does it strip types and yolo
       | trying to run or will it spit out type errors?
        
         | TheRealPomax wrote:
         | Why would you describe that "yolo"? If you're writing TS, you
         | already have a TS linter that checks whether code has typing
         | problems or not (at least, I certainly hope you do?). It's not
         | really Node's job to do that linting, its job is to execute the
         | JS that's hiding in the TS. It'd be "handy" if it did, but it'd
         | also be a bit weird when there are already TS linting tools.
         | It'd just hold up landing any sort of TS support that much
         | longer.
        
         | bentruyman wrote:
         | If you read the third sentence of the PR, it says:
         | 
         | > During the transpilation process, no type checking is
         | performed, and types are discarded
        
         | Shacklz wrote:
         | If I understood correctly they use a wrapper around swc to
         | strip types, without any type-check being performed.
         | 
         | Which makes perfect sense to start out with; as typechecking
         | with tsc is rather slow and can easily be delegated to the
         | consumer.
        
       | ofirg wrote:
       | support for typescript as long as you are only using it for type
       | checking, not if you are also using features that are not
       | supported in the javascript version you are targeting.
        
         | paulddraper wrote:
         | That is what people use TypeScript for generally.
         | 
         | If you need JS syntax features that Node.js doesn't support you
         | can use tsc, babel, etc.
         | 
         | Because obviously unsupported features are unsupported, whether
         | JS or TS.
        
         | flohofwoe wrote:
         | > not if you are also using features that are not supported in
         | the javascript version you are targeting. reply
         | 
         | This is only 'half-assed' anyway, TS will only emulate new
         | language features on older JS target version, but not any
         | Javascript _runtime_ features (like new Object methods). For
         | the latter you will still need a separate polyfill solution.
        
       | samtheprogram wrote:
       | Bun's DX is pretty unprecedented in this space, and most of my
       | use cases are now covered / not causing Bun to crash (when
       | actually using run-scripts with `bun run`).
       | 
       | Meanwhile, I can't configure node to not require extensions on
       | import, nor have tsc configured to automatically add .js
       | extensions to its compiled output, without adding on a bundler...
       | although native TypeScript support would remedy this nit quite a
       | bit, I can't imagine the user experience (or performance) to
       | match Bun's when it reaches stable.
        
         | spankalee wrote:
         | Extensions _should_ be required. It 's not possible to do path
         | searches over the network like you can on local disk, and
         | network-attached VMs, like browsers, are a very, very important
         | runtime for JavaScript.
        
           | samtheprogram wrote:
           | That makes sense. I guess since using .js for the relevant
           | imports just works in TypeScript I should be happy then...
        
           | leipert wrote:
           | Also performance.
           | 
           | foo could mean foo/index.js, foo.js at the minimum. So you
           | have 2x the lookups. Oh no, wait we also potentially have
           | mjs, cjs, jsx, ts and tsx.
           | 
           | So 12 times the stat checking for each import.
        
             | simlevesque wrote:
             | > foo could mean foo/index.js, foo.js at the minimum. So
             | you have 2x the lookups.
             | 
             | Only in the worst case. If it's foo.js there's only one
             | lookup.
             | 
             | > Oh no, wait we also potentially have mjs, cjs, jsx, ts
             | and tsx. So 12 times the stat checking for each import.
             | 
             | Again, you're only taking into account the worst case.
        
           | pfg_ wrote:
           | Fortunately, code is generally bundled for browsers to reduce
           | the number of network requests and total size of downloads.
           | And node has access to the filesystem, so it can do path
           | searches just fine if it wants to support existing code.
        
             | WorldMaker wrote:
             | You probably don't need a bundler in the browser anymore.
             | We're not yet to the point that is a popular "mainstream"
             | opinion, but between massive improvements in browser
             | connection handling (HTTP 1.1 connection sharing actually
             | works in more places, HTTP/2+) and very good ESM support in
             | browser's well optimized preloaders and caching engines
             | (which can sometimes reduce download size _much better_
             | than all-or-none bundles can, sure the trade-off is network
             | requests but we are in a good place to take that trade-
             | off), we 're at an exciting point where there is almost
             | never a need to bundle in development environments, and it
             | is increasingly an option to not bundle in production
             | either. It is _worth_ benchmarking today (I can 't tell you
             | what your profiler tools will tell you) if you are really
             | gaining as much from production bundles as you think you
             | are. Not enough people are running those benchmarks, but
             | some of them may already be surprised.
             | 
             | The Developer Experience of unbundled ESM is _great_. Of
             | course you do need to do things like always use file
             | extensions. But those aren 't hard changes to make, worth
             | it for the better Developer Experience, and if it can help
             | us start to wean off of mega-bundler tools as required
             | production compile time steps.
        
               | tubs wrote:
               | Meh. Even with h3 I still see more gains from reducing
               | network requests than most other attempts I try. (One day
               | s3 will support multiple ranges per request, if I wish
               | hard enough).
        
           | silverwind wrote:
           | Yeah, besides that, leaving out the extension also creates
           | ambiguity when the same filename exists with multiple file
           | extensions.
        
         | hackandthink wrote:
         | "nor have tsc configured to automatically add .js extensions to
         | its compiled output"
         | 
         | It seems to be the default now:                 $echo
         | 'console.log("test")' > t.ts       $ tsc t.ts       $ ls
         | t.js  t.ts       $ node t.js       test
        
           | boromisp wrote:
           | What they probably meant was writing 'import "file.ts"' and
           | have tsc emit 'import "file.js"'.
           | https://github.com/microsoft/TypeScript/issues/49083
        
             | WorldMaker wrote:
             | Given the context of Node here will allow experimental
             | type-stripping and will not be doing things like import
             | rewriting, Typescript's decision here to focus on "users
             | write .js in imports because that's how the type-stripped
             | file should look" seems like the right call to me. Less
             | work for a type-stripper because Typescript can already
             | check if there is a .ts or .d.ts file for you if you use
             | .js imports everywhere.
        
         | IshKebab wrote:
         | > unprecedented
         | 
         | Well except for Deno...
        
           | pas wrote:
           | Bun started with compatibility with NodeJS as a primary goal,
           | whereas for Deno it took a while to be able to import npm
           | stuff. (Of course there are fun WTF[0] errors with Bun, and I
           | only tried Deno before the npm import feature landed.)
           | 
           | [0] https://github.com/oven-sh/bun/issues/11420
        
         | k__ wrote:
         | Bun is pretty awesome.
         | 
         | However, the node:crypto module still doesn't work 100%. So, I
         | can't use it yet.
        
           | tossandthrow wrote:
           | The parallel implementation they do uncovers a number of
           | unexpected behaviors in the node implementation.
        
         | oblio wrote:
         | Isn't Bun too raw? It's built with Zig, which hasn't even hit
         | 1.0.
        
           | laxis96 wrote:
           | Probably had to stay in the oven a bit longer...
           | 
           | Jokes apart, Zig is moving forward a lot which is why it's
           | not 1.0 yet, but it doesn't mean you can't write safe and
           | performant applications right now.
           | 
           | Zig is also a rather simple and straightforward language
           | (like C) and has powerful compile-time code generation (like
           | C macros, but without the awful preprocessor).
        
             | oblio wrote:
             | I'm more worried about compilation or stdlib bugs. In
             | theory you can do lots of things with lots of things, but
             | in practice there are all sorts of hidden limitations and
             | bugs that tend to be noticed once a software product is
             | past 1.0 and has been out in the wild for half a decade or
             | more.
        
           | jokethrowaway wrote:
           | You still get segmentation faults. My biggest complain with
           | bun is not having enough safety.
           | 
           | If you use frameworks written for node memory usage is very
           | high and performance is meh.
           | 
           | If you use frameworks written for bun they smoke anything on
           | node.
           | 
           | I'd definitely move over, just to get rid of the whole
           | TypeScript / cjs / esm crap, but:
           | 
           | 1. frontend support is poor (next.js / solid.js - I can't run
           | anything fully on bun)
           | 
           | 3. I still need to rewrite my backend app from a node.js
           | framework to a bun one
           | 
           | 4. for backend development the javascript ecosystem is losing
           | the crown: if I wanted something safe I'd just write it in
           | Rust (TS allows any random developer to write crap with any
           | in it and it validates), if I'm doing something AI related
           | I'd probably need python anyway and fastapi is not half bad
        
         | WuxiFingerHold wrote:
         | I like Bun a lot, but Deno is (still) the more mature, stable,
         | capable (e.g. stable workers, http2) and depending on the use-
         | case more performant option (V8 > JSC). DX and tooling is top-
         | notch. Deno can perform typchecking, btw. They bundle the TSC
         | IIRC. Bun is the hype, but Deno is currently clearly the better
         | option for serious endevours. Still, the vision and execution
         | of Bun is impressive. Good for us devs.
        
         | XCSme wrote:
         | I tried Bun twice, months apart, it never worked for me on
         | Windows, failing to run "bun install":
         | https://github.com/search?q=repo%3Aoven-sh%2Fbun+bun+install...
        
       | spankalee wrote:
       | It's about time for TC39 and Microsoft to standardize TypeScript
       | as part of JavaScript. Not "types as comments" either, but
       | actually TypeScript, minus the non-standard runtime semantics and
       | modulo whatever changes are necessary to integrate the grammar.
       | 
       | So many runtimes and tools are integrating TypeScript now, and
       | with multiple implementations, that a real standard is necessary.
       | It'll be much harder to evolve TypeScript because it'll have to
       | stay backwards compatible, but it's grown to that point now, imo.
        
         | vivzkestrel wrote:
         | its about time google chrome started making a typescript engine
         | maybe? and get rid of JS in phases?
        
           | jjk7 wrote:
           | There are a few optimizations that types can use but 99% of
           | applications wouldn't benefit from them anyways.
        
             | Shacklz wrote:
             | Taking one link out of the toolchain (tsc) would already be
             | a huge blessing.
             | 
             | And naive me hopes for a future where in my web-app I can
             | set a policy that any non-ts, type-incompliant code is not
             | allowed to run.
             | 
             | The amount of exceptions I get in the console from terrible
             | garbage-code outside of my control but that I have to
             | include because enterprise is staggering. Would love to
             | have a meta-setting which would just kill them if they
             | can't be arsed to even have a modicum of code-hygiene
             | (sorry for the rant)
        
               | _flux wrote:
               | Why is taking out the part that actually checks the types
               | at the developer's side a huge blessing?
               | 
               | Or if you are hoping to get the benefit of type checking
               | in the browser itself (taking the same sweet time as tsc,
               | but this time on every browser instead of once in the
               | CI), then how long would you want to wait to be able to
               | actually use the new typing functionality described in
               | e.g. the latest TS annoucement?
               | https://devblogs.microsoft.com/typescript/announcing-
               | typescr... .
               | 
               | Because it would take a while until that would then
               | become the standard and then become available in every
               | browser. And you _still_ need to provide the JS versions,
               | because not every browser is going to support TS.
               | 
               | In the meanwhile you could just keep using tsc just as
               | before and get access to new functionality immediately.
               | 
               | (I imagine you could run tsc in the browser right now if
               | you really wanted to.)
        
               | Shacklz wrote:
               | > Why is taking out the part that actually checks the
               | types at the developer's side a huge blessing?
               | 
               | Oh, no, certainly we want to keep type-checking in the
               | pipeline, somewhere.
               | 
               | However, if the browser "understood" typescript, your
               | codebase could have immediate hot-reload, without any
               | transpilation in-between. The type-checking could then be
               | (and already is when using something like esbuild/swc) an
               | entirely separate process that happens independently.
               | 
               | Webpack's HMR is pretty good, but not having to modify
               | the code _at all_ to have it work in the browser, that 'd
               | be much much better :)
               | 
               | ... the browser being able to typecheck (and reject
               | violating code) itself is certainly something I'd love to
               | see eventually, but fully agreed, this is not happening
               | anytime soon.
        
             | flohofwoe wrote:
             | One advantage of Typescript in context of performance
             | should be that it nudges one to not change the 'shape' of
             | runtime objects too much, this should allow less runtime
             | overhead in JS engines because code doesn't need to be re-
             | jitted as often.
             | 
             | This doesn't require the type annotations at runtime
             | though, it's just a side effect of code being written
             | against a static type system.
        
           | crabmusket wrote:
           | This is a persistent meme that has no basis in reality. A
           | TypeScript engine _is_ a JavaScript engine, since everything
           | that can be done in JS can be done in TS. It 's plausible,
           | maybe, that there could be some additional optimisations on
           | TS code where the engine is sufficiently happy with all types
           | in a subset of the program. But that would be _on top of_ all
           | existing JS engine features, unless you want your engine 's
           | performance to suddenly degrade if you stray outside the
           | fully-statically-verifiabe-TS happy path.
        
             | dtech wrote:
             | That's a pretty obtuse interpretation of the comment.
             | Browsers natively being able to run Typescript code / .ts
             | files instead of requiring transpiling to plain Javascript
             | would be a large boon to the TS ecosystem by making
             | basically everything easier. Even if it's just stripping
             | the TS and running the plain JS it would already be
             | helpful, but it running the typechecking beforehand would
             | be wonderful.
        
               | crabmusket wrote:
               | Maybe I was reading too much into the comment I replied
               | to, but to me "a typescript engine" implied more than
               | "ignoring the types" (which is the current TC39
               | proposal).
               | 
               | And I was replying based on what I've seen other people
               | saying whenever the subject comes up; apologies if I
               | misread.
               | 
               | Browsers doing type checking is a pretty fraught idea
               | IMO, at least with Typescript and not some other
               | statically typed language entirely.
        
           | mcintyre1994 wrote:
           | A lot of apps would (or at least should) still want to strip
           | types for bundle size reasons though.
           | 
           | To take one extreme example, a library I work on includes an
           | API for calling a JSON RPC server. Instead of manually
           | implementing each call, we use a proxy object that converts
           | any method call on it to a JSON RPC call. Then layer on types
           | so given an RPC object you know every method on it and have
           | typed input params and output. This means you can have any
           | number of methods without increasing your bundle size,
           | because all the types disappear at runtime. It also means you
           | can add your own methods if you're talking to a server that
           | implements custom ones by just defining types. If you shipped
           | this to the browser with the types then it'd be a much bigger
           | bundle than without them.
        
           | rty32 wrote:
           | My take as an outsider: Google has absolutely no interest in
           | this, especially with their recent cost-cutting measures.
           | Google cares about things that make the "web" better for the
           | end users so that they can sell more ads, not developer
           | tools. TypeScript or JavaScript doesn't matter that much to
           | Google, and actually Google probably doesn't want to see
           | TypeScript files distributed over network (which doesn't make
           | much sense in the first place). In all honesty, Microsoft
           | understands development experience much better than Google
           | and most other companies. They literally own Visual Studio,
           | Visual Studio Code and GitHub and sell products/services for
           | money.
        
         | mythz wrote:
         | This has been proposed for several years now, but there's been
         | very little progress on it:
         | 
         | https://github.com/tc39/proposal-type-annotations
        
           | spankalee wrote:
           | That is "types as comments", not standardizing TypeScript.
        
             | dgellow wrote:
             | It is explicitly not type as comments, it is type erasure
        
               | spankalee wrote:
               | > This proposal aims to enable developers to add type
               | annotations to their JavaScript code, allowing those
               | annotations to be checked by a type checker that is
               | external to JavaScript. At runtime, a JavaScript engine
               | ignores them, treating the types as comments.
        
               | dgellow wrote:
               | Yes, that's explaining what type erasure is. "type as
               | comments" is what Flow supports, literal comments for
               | type annotations.
               | 
               | I think we disagree on the terminology but agree on the
               | goal of the proposal
        
               | pcthrowaway wrote:
               | Types as comments is what jsdoc supports. Flow is
               | compiled like typescript.
               | 
               | tsc _does_ also support jsdoc though, so technically I
               | think tsc is closer to supporting types as comments,
               | though it 's possible Flow has this also.
        
               | dgellow wrote:
               | https://flow.org/en/docs/types/comments/
        
               | pcthrowaway wrote:
               | Thanks, I've never used flow and didn't know this. I've
               | only seen it used in the non-comment form.
        
               | spankalee wrote:
               | Types _in_ comments is different from types _as_
               | comments. "Types as comments" refers to how type
               | expressions are parsed.
        
               | pcthrowaway wrote:
               | jsdoc is a format for supplying types (and annotations)
               | as comments as well.
               | 
               | I think I get the distinction you're trying to make, but
               | I don't think the nuance there is significant enough to
               | merit differentiating the two.
        
               | eyelidlessness wrote:
               | The proposal would explicitly treat supported type
               | annotation syntax _as comments in the grammar_. It is
               | definitely types as comments, even if it is _also_ type
               | erasure.
               | 
               | And it would apply to Flow's type annotation syntax which
               | is also not presently treated as comments, at least for
               | the very large subset of that syntax which overlaps with
               | the proposal.
        
               | dgellow wrote:
               | I meant https://flow.org/en/docs/types/comments/
        
               | eyelidlessness wrote:
               | I know what you meant.
        
               | spankalee wrote:
               | "types as comments" is the term that the champions and
               | reviewers of this proposal have been using.
               | 
               | It refers to how the types are parsed: aside from some
               | kind of standard start and end delimiters, the parser
               | does not try to parse the expression-level type syntax.
               | Type expressions are just strings of characters. This way
               | you can have basically any syntax at all for types.
        
               | crabmusket wrote:
               | That has no bearing on the comment you're replying to.
               | 
               | The point is that the types could be TypeScript, Flow,
               | Hegel, or something else. The browser won't perform type
               | checking, it will just ignore the types.
               | 
               | So, it is not standardising TypeScript.
        
               | jraph wrote:
               | I believe you and several of your child comments might be
               | confusing "types as comments" with "types in comments".
        
               | madeofpalk wrote:
               | It explicitly is, from the link
               | 
               | > At runtime, a JavaScript engine ignores them, treating
               | the _types as comments_.
               | 
               | The phrasing here is that the types are meaningless. They
               | are just "comments" to the JS engine.
        
         | paulddraper wrote:
         | TypeScript used to have a standard.
         | 
         | Years and years ago. Now it's whatever the compiler does.
         | 
         | Which to be fair, is evolving quite rapidly.
        
           | spankalee wrote:
           | Yeah, that was from 2016 or so. But a TypeScript spec is
           | different than folding TypeScript into the ECMAScript
           | standard. Some parts of TypeScript would have to be dropped
           | or changed for that to work.
        
             | paulddraper wrote:
             | Right, having a spec is easier (and effectively
             | prerequisite) to your suggestion.
             | 
             | But they don't have it.
        
         | tylerchilds wrote:
         | i'm not sure i buy the "company floods the industry with broken
         | tooling and deserves to be standardized" narrative.
         | 
         | yeah, the ecosystem sucks, but rewarding the system
         | incentivized to co-opt the system will actually make things
         | worse in the long run, not better.
         | 
         | for example, internet explorer failed why?
        
           | dgellow wrote:
           | What broken tooling are you talking about? tsc is broken?
           | 
           | IE failed because it was a horrible browser that didn't
           | evolve for years and was incompatible with major web standard
           | developments. Nothing to do with typescript, an open source,
           | best in class type system and type checker.
        
             | tylerchilds wrote:
             | IE failed because they tried to define the standard as
             | themselves. i argue we're witnessing that again from the
             | same company that only gave up that strategy once they had
             | typescript, github, npm locked in.
             | 
             | i'm not bullish on political strategies being technical
             | solutions, which is the premise.
             | 
             | typescript has nothing to do with internet explorer, true,
             | but is it really not obvious that it is the same tactic as
             | a different brand? become the standard, steer the
             | committee.
             | 
             | and broken in that copying code between systems requires
             | compatibility between configurations, which should be a red
             | flag for any language.
        
             | tylerchilds wrote:
             | "During the transpilation process, no type checking is
             | performed, and types are discarded."
             | 
             | this node feature is primarily around disregarding
             | typescript in favor of the underlying javascript it
             | represents.
             | 
             | that reminds me of this fun article: https://www.richard-
             | towers.com/2023/03/11/typescripting-the-...
        
               | dgellow wrote:
               | Yes, the feature is about being able to run typescript
               | scripts. It's not a type checker, it is similar to ts-
               | node, deno, bun, etc. Typescript has been designed for
               | that specific purpose.
        
               | tylerchilds wrote:
               | seen and heard, my original point was that typescript is
               | not poised to be a tc39 standard.
               | 
               | this is still a "runs some typescript" and "not runs
               | every typescript file"
               | 
               | " At least initially in this PR no trasformation is
               | performed, meaning that using Enum, namespaces etc...
               | will not be possible."
               | 
               | this type of nuance is the core of why typescript is a
               | headache for any organization with more than a single
               | codebase-- javascript is portable, typescript is in
               | theory, but not in observed practice.
        
         | dgellow wrote:
         | I would rather let Typescript evolve a few more years before
         | freezing its development via standardization
        
           | suby wrote:
           | I'm interested to know what are some things that you (or
           | anyone reading this) feels that Typescript is missing /
           | should change?
        
             | _flux wrote:
             | I don't have a list and I don't even write TS (or do much
             | web dev in general), but I do follow their announcements
             | and it seems every one of them brings new big type things.
             | 
             | Nevertheless, I don't see TS support in e.g. browsers being
             | anything useful, as in practice all JS code deployed is
             | already packaged somehow, so the stage to convert TS to JS
             | (and then also checking the types..) fits that just fine.
             | It's useful for hobbyists, but I don't that is a reason
             | enough to come up with a standard.
        
             | rty32 wrote:
             | One example:
             | 
             | https://github.com/microsoft/TypeScript/issues/30551
             | 
             | Which goes to
             | https://github.com/microsoft/TypeScript/issues/9998 which
             | captures a lot of such scenarios
             | 
             | And just a few releases ago there were some big problems
             | with handling recursive types. I think most are fixed but
             | there may still be a few around.
             | 
             | These are things that you run into on a daily basis if you
             | write enough TypeScript.
             | 
             | I doubt we should standardize TypeScript before we have
             | definitive solutions to all these. And I 100% agree with
             | the parent's comment.
        
             | low_tech_punk wrote:
             | Maybe it's helpful to analyze TypeScript's track record in
             | deprecating features and creating breaking changes, which
             | could be a big red flag to TC39. I'm all for typing support
             | but my work is mostly prototyping on short lived projects.
             | People maintaining production systems that will eventually
             | become legacy systems might have a different opinion.
        
           | pas wrote:
           | C++ and Java are quite good at churning out standard docs and
           | new versions every few years. (Even Python is aiming to offer
           | GIL-lessness!)
        
         | silverwind wrote:
         | Imho standardizing the syntax is enough and this is what
         | https://github.com/tc39/proposal-type-annotations does.
         | 
         | The type checker is immensely complex and should be left out so
         | that other type checkers can be developed, e.g. similar to how
         | it's for Python today.
        
           | spankalee wrote:
           | That doesn't standardize the syntax, only types-as-comments.
           | It would have to standardize some delimiters for type
           | expressions, but that's it.
           | 
           | I do think that the semantics should be standardized too,
           | otherwise you have non-interoperable types. The goal should
           | be that you can use two libraries together without having to
           | make sure they use the same type-checker.
        
         | pier25 wrote:
         | Another reason is probably performance. Executing TS would
         | require a lot of extra CPU and even more energy than JS.
         | 
         | A lot of effort and money has been invested into JS engines. I
         | wonder if making a TS native engine (which nobody has made yet)
         | from scratch might make more sense than adapting JS engines to
         | run TS.
        
         | hajile wrote:
         | TS is an intentionally unsound type system that tries to allow
         | you to type your code no matter if it will run like garbage, is
         | unreadably complex, and uses terrible parts of the language.
         | 
         | What TC39 needs is a type system that limits what you can do to
         | things that are sound, performant, and good practice. TS is the
         | exact opposite of this.
        
       | throwitaway1123 wrote:
       | It's been a really eventful month for Node. First they added
       | node:sqlite in v22.5.0, and now TypeScript support is landing. I
       | love the direction Node is heading in.
        
         | crabmusket wrote:
         | The recently-added test runner is very cool too!
        
           | SwiftyBug wrote:
           | YES. It was such a joy to be able to ditch Jest completely
           | and run tests natively.
        
             | joseferben wrote:
             | i tried that but had to revert to vitest, the native test
             | runner feels incomplete atm.
        
               | crabmusket wrote:
               | What is missing for your use case or workflow?
        
               | sureIy wrote:
               | Probably a bunch of assertion types and general DX.
               | Node:test is just a feature, Vitest is a whole product.
               | The former might be enough for small packages but nowhere
               | near useful for anything non-trivial.
        
           | conaclos wrote:
           | I tested it a few months ago. However, the output isn't very
           | human friendly.
        
           | herpdyderp wrote:
           | I just started using it the other day and it's a dream. I
           | look forward to the eventual stability of their snapshot
           | testing.
        
         | eknkc wrote:
         | It is Bun influence / competition I guess. Good for everyone.
        
           | mark_and_sweep wrote:
           | I believe the competition started with Deno. But yes, Bun is
           | part of the competition now, too.
        
             | eknkc wrote:
             | Deno was doing its own thing though.
             | 
             | Bun came out swinging with strong Node.JS compatibility
             | promises. I have simply replaced node with bun for most of
             | my own work without much effort. The mental effort required
             | is to use `bun` instead of `node` in command line for most
             | of the trivial things.
        
       | just-tom wrote:
       | Nice, but without support for Enums, for me it's mostly useless.
        
         | Shacklz wrote:
         | In our codebase we started to disallow enums in favour of
         | string literal types, and once folks get over the ingrained
         | "this needs to be an enum" (coming mostly from other languages
         | like Java), it's not much missed.
         | 
         | Enums are one of the very few things in typescript that seem to
         | not have turned out that well, but it's relatively easy to work
         | without them with string-literable types and such, derived from
         | some const in case they're also needed at runtime.
        
           | shepherdjerred wrote:
           | 100% agree. Coming from Java I really wanted an Enum type,
           | but string literals/discriminated unions fill that niche just
           | fine.
        
           | bythreads wrote:
           | agree enums in typescript are the devil
        
             | revskill wrote:
             | Could u explain why ?
        
         | azangru wrote:
         | There are union types for strings; and there are plain
         | javascript objects (typed as const) if "namespace.name" syntax
         | is desired. With these available, what is the point of enums?
        
           | silverwind wrote:
           | Namespaces are also not supported as per https://github.com/n
           | odejs/node/blob/main/doc/api/typescript.....
           | 
           | I for one can can live without all these features and will be
           | banning via eslint.
        
             | azangru wrote:
             | Yes. Both namespaces and enums (and probably the "private"
             | keyword on class methods) are an early addition to the
             | language, which would have never been added if typescript
             | from the very start aligned closely with Ecmascript.
        
       | Shacklz wrote:
       | I'm honestly giddy. This could be the (slow) beginning of a new
       | era, where "JS with types" is finally a native thing.
       | 
       | I'm even willing to forgive all the mess that CJS vs. ESM is if
       | they manage to pull this off.
       | 
       | I hope this sees widespread adoption/usage, which might _finally_
       | cause some movement to integrate TS into ecmascript after all.
       | Some dynamically-typed language fanatics (which are, in my
       | opinion, completely detached from the reality that static types
       | are what the vast majority of devs want) still have an iron grip
       | on TC39, this might be the start of their end. And good riddance.
        
         | yashap wrote:
         | Yeah, my personal experience is that easily 95% of devs I work
         | with/have met in person, if not closer to 99%, prefer
         | statically typed languages. Maybe that's a biased sample, but I
         | do think the overall preference among devs is very strong. I
         | also see JS slowly, more-or-less becoming TypeScript over time.
        
           | tstrimple wrote:
           | My days of being a real software developer are long behind
           | me. So I'm totally willing to accept that I'm wrong here. But
           | when I build a POC in particular, there's a LOT of power and
           | flexibility granted by not giving a fuck about types.
           | Suddenly I can accept non well defined data types (depending
           | on my implementation) and can persist data that otherwise
           | would have taken code changes and approval processes to
           | accept. I do believe there is a place for types, but to type
           | all the things is folly. There are capabilities within
           | JavaScript to handle both.
        
             | iamsaitam wrote:
             | The malicious beauty of typescript is that at any point you
             | can just declare something "any" and voila, the guard rails
             | are off.
        
             | miunau wrote:
             | Just use `any` or `unknown` when prototyping, then apply
             | types once your happy paths start working for the first
             | time to start catching the unhappy ones.
        
               | djeastm wrote:
               | >then apply types once your happy paths start working for
               | the first time to start catching the unhappy ones.
               | 
               | I.e. the "I'll go back and add safety later" strategy.
               | Somehow I never seem to get around to doing it.
        
             | iainmerrick wrote:
             | _when I build a POC in particular, there 's a LOT of power
             | and flexibility granted by not giving a fuck about types_
             | 
             | I find the same thing, but only for _very_ small throwaway
             | scripts and the like. For anything beyond like 20 lines of
             | code, I rapidly hit confusing cases like "is this parameter
             | just a map, or a map or maps?" Then I add types and it
             | makes sense again.
        
           | spaceheater wrote:
           | Let's make it 94 then. I think typescript is an abomination
           | forced by java developers that don't want to learn
           | javascript.
        
             | wiseowise wrote:
             | Guard rails on a bridge are an abomination forced onto us
             | by government because people don't want to learn how to
             | fly.
        
         | jampekka wrote:
         | > the reality that static types are what the vast majority of
         | devs want
         | 
         | [citation needed]
        
           | wiseowise wrote:
           | https://github.com/tc39/proposal-type-
           | annotations?tab=readme...
           | 
           | You're welcome.
        
             | dgb23 wrote:
             | This is not what GP asked for. That's the most requested
             | feature from the state of JS survey.
             | 
             | I bet the percentage of web developers who want this are a
             | tiny minority. There are just too many issues with this.
             | 
             | Static typing without the benefits of better runtime
             | performance, soundness, strong typing etc. is basically
             | just documentation/comments with extra steps.
             | 
             | Also TS is a complex, moving target. Most devs don't want
             | to learn new fancy features every couple of months, but
             | prefer stability guarantees. Several notable projects have
             | moved away from TS. Even Ryan Dahl admitted that
             | integrating Deno with TS was probably a mistake.
             | 
             | Meanwhile you have WASM slowly and steadily getting crucial
             | features on a sound foundation.
             | 
             | I'm extremely cautious about TS and wary of the hype
             | surrounding it.
        
           | wokwokwok wrote:
           | The reaction emoji on the merged PR are not particularly
           | ambiguous.
        
       | pansa2 wrote:
       | If Node.js can run TypeScript files directly, then the TypeScript
       | compiler won't need to strip types and convert to JavaScript - it
       | could be used solely as a type checker. This would be similar to
       | the situation in Python, where type checkers check types and
       | leave them intact, and the Python interpreter just ignores them.
       | 
       | It's interesting, though, that this approach in Python has led to
       | several (4?) different popular type checkers, which AFAIK all use
       | the same type hint syntax but apply different semantics. However
       | for JavaScript, TypeScript seems to have become the one-and-only
       | popular type checker.
       | 
       | In Python, I've even heard of people writing types in source code
       | but never checking them, essentially using type hints as a more
       | convenient syntax for comments. Support for ignoring types in
       | Node.js would make that approach possible in JavaScript as well.
        
         | winter_blue wrote:
         | Flow (by Facebook) used to be fairly significant in the
         | JavaScript several years ago, but right now it's somewhat clear
         | that TypeScript has won rather handily.
        
           | mattnewton wrote:
           | Before that there was the closure compiler (Google) which had
           | type annotations in comments. The annotation syntax in
           | comments was a little clunky but overall that project was
           | ahead of it's time. Now I believe even inside google that has
           | been transpiled to typescript (or typescript is being
           | transpiled to closure, I can't remember which - the point is
           | that the typescript interface is what people are using for
           | new code).
        
             | LoganDark wrote:
             | Oh, Closure Compiler is such a throwback. I still remember
             | staring at the project page on Google Code. Isn't it like
             | two decades old or even older by this point? Is it still
             | alive?
        
               | mdhb wrote:
               | The compiler itself lives on but it works with TypeScript
               | now rather than the JSDoc comments style approach which
               | is officially EOL AFAIK.
        
               | flohofwoe wrote:
               | Closure is still used in Emscripten to optimize the
               | generated Javascript shim file.
        
               | rty32 wrote:
               | This can give you some hints of the current status of
               | closure compiler:
               | 
               | https://github.com/google/closure-compiler/issues/2731
               | 
               | I happen to know this because we have some old projects
               | that depend on this and are working hard to get rid of
               | the dependency.
               | 
               | I wish Google either updates it or just mark the whole
               | thing deprecated -- the world has already moved on
               | anyway. Relating this to Google's recent cost cutting,
               | and seeing some other Google's open source projects more
               | or less getting abandoned, I have to say that today's
               | Google is definitely not the same company from two
               | decades ago.
        
             | miki123211 wrote:
             | Closure was also interesting because it integrated type
             | checking and minification, which made minification
             | significantly more useful.
             | 
             | With normal Javascript and typescript, you can't minify
             | property names, so `foo.bar.doSomethingVeryComplicated()`
             | can only be turned into
             | `a.bar.doSomethingVeryComplicated()`, not `a.b.c()`, like
             | with Closure. This is because objects can be indexed by
             | strings. Something like `foo.bar[function]()` is perfectly
             | valid JS, where the value of `function` might come from the
             | user.
             | 
             | A minifier can't guarantee that such expressions won't be
             | used, so it cannot optimize property accesses. Because
             | Closure was a type checker and a minifier at the same time,
             | it could minify the properties declared as private, while
             | leaving the public ones intact.
        
               | wiktor-k wrote:
               | > Something like `foo.bar[function]()` is perfectly valid
               | JS,
               | 
               | A minor thing but `function` is a keyword in JS so
               | technically it's not a "perfectly valid JS".
        
               | mkesper wrote:
               | Oh boy, just think functionName and it fits.
        
               | mananaysiempre wrote:
               | > A minifier can't guarantee that such expressions won't
               | be used, so it cannot optimize property accesses.
               | 
               | Given TypeScript's type system is unsound, neither could
               | it even if it tried, right? I guess Flow could, but well,
               | here we are.
        
               | afavour wrote:
               | Theoretically TS could... until it encounters an 'any'
               | type in that code path, then it would have to give up.
               | 
               | But there are TSconfig options to ensure no use of any so
               | with the right level of strictness it could happen.
        
               | epolanski wrote:
               | What do you mean by unsound exactly.
               | 
               | I'm asking because there's no accepted definition of what
               | an unsound type system is.
               | 
               | What I often see is that the word unsound is used to mean
               | that a type system can accept types different to what has
               | been declared, and in that case there's nothing unsound
               | about ts since it won't allow you to do so.
        
               | sharlos201068 wrote:
               | That's not correct, there's several ways the actual type
               | of a value differs from what typescript thinks it is. But
               | soundness isn't a goal of typescript.
        
               | WorldMaker wrote:
               | It's maybe useful to note in this discussion for some
               | that "soundness" of a type system is a bit of
               | technical/theoretical jargon that in some cases has
               | specific mathematical definitions and so "unsound" often
               | sounds harsher (connotatively) than it means. The vast
               | majority of type systems are "unsound" for very pragmatic
               | reasons. Developers don't often care to work in a "sound"
               | type systems. Some of the "most sound" type systems we've
               | collectively managed to build are in things like theorem
               | provers and type assertion systems that some of us don't
               | always even consider useful for "real" software
               | development.
               | 
               | Typescript is a bit more unsound than most because of the
               | escape hatch `any` and because of the (intentional)
               | disconnect between compiler and runtime environment. Even
               | though "unsound" sounds like a bad thing to be, it's a
               | big part of why Typescript is so successful.
        
               | cstrahan wrote:
               | > and in that case there's nothing unsound about ts since
               | it won't allow you to do so
               | 
               | Consider this example (https://www.typescriptlang.org/pla
               | y/?ssl=10&ssc=1&pln=1&pc=1...):                 function
               | messUpTheArray(arr: Array<string | number>): void {
               | arr.push(3);       }              const strings:
               | Array<string> = ['foo', 'bar'];
               | messUpTheArray(strings);              const s: string =
               | strings[2];       console.log(s.toLowerCase())
               | 
               | Could you explain how this isn't the type system
               | accepting types "different to what has been declared"?
               | Kinda looks like TypeScript is happy to type check this,
               | despite `s` being a `number` at runtime.
        
               | epolanski wrote:
               | That's a good example, albeit quite of a far-fetched one.
               | 
               | In Haskell land, where the type system is considered
               | sound you have `head` functions of type `List a -> a`
               | that are unsound too, because the list might be empty.
        
               | crdrost wrote:
               | That option also exists, you can just leave out the
               | `messUpTheArray` lines and you get an error about how
               | `undefined` also doesn't have a `.toLowerCase()` method.
               | 
               | However this problem as stated is slightly different and
               | has to do with a failure of OOP/subtyping to actually
               | intermingle with our expectations of covariance.
               | 
               | So to just use classic "animal metaphor" OOP, if you have
               | an Animal class with Dog and Cat subclasses, and you
               | create an IORef<Cat>, a cell that can contain a cat, you
               | would like to provide that to an IORef<Animal> function
               | because you want to think of the type as covariant: Cat
               | is a subtype of Animal, F<Cat> should be a subtype of
               | F<Animal>. The problem is that this function now has the
               | blessing of the type system to store a Dog in the cell,
               | which can be observed by the parts that still consider
               | this an IORef<Cat>.
               | 
               | Put slightly differently, in OOP, the methods of
               | IORef<Cat> all accept an implicit IORef<Cat> called
               | `this`, if those methods are part of what define an
               | IORef<x> then an IORef<x> is necessarily invariant, not
               | covariant, in <x>. And then you can't assume subtyping.
               | So to be sound a subtype system would presumably have to
               | actually mark contra/covariance around _everything_ , and
               | TypeScript very intentionally documents that they _don
               | 't_ do this and are just trying to make a "best effort"
               | pass because JavaScript has 0 types, and crappy types are
               | better than no types, and we can't wait for perfect types
               | to replace the crappy types.
        
               | cstrahan wrote:
               | > In Haskell land, where the type system is considered
               | sound you have `head` functions of type `List a -> a`
               | that are unsound too, because the list might be empty.
               | 
               | Haskell's `head` not is not an example of the type system
               | being unsound (I stress this point because we've been
               | talking about type system soundness, not something-else-
               | soundness).
               | 
               | From the view of the type system, `head` is perfectly
               | sound: if the list is empty, the resulting value is [?]
               | ("bottom"). And [?] is an inhabitant of every type.
               | Therefore, `head` returning [?] when given an empty list
               | is perfectly fine. When you force [?] (i.e. use it _any_
               | way whatsoever), an exception is thrown. See
               | https://wiki.haskell.org/Bottom
               | 
               | This is very much _not_ the same thing (or remotely
               | analogous) to what we have in my TypeScript example.
               | There, the code fails at runtime when I attempt to call
               | `toLowerCase`, yes; what 's worse is the slightly
               | different scenario where we succeed in calling something
               | we shouldn't:                 class Person {
               | name: string;                 constructor(name: string) {
               | this.name = name;         }                 kill() {
               | console.log("Killing: " + this.name);         }       }
               | class Murderer extends Person { }              class
               | Innocent extends Person { }              function
               | populatePeopleFromDatabase(people: Array<Innocent |
               | Murderer>): void {           // imagine this came from a
               | real SQL query           people.push(new
               | Innocent("Bob"));       }                     function
               | populateMurderersFromDatabase(people: Array<Murderer>):
               | void {           // TODO(Aleck): come back and replace
               | this with a query that only selects murderers.
               | //              i wanted to get the rest of the code in
               | place, and this type checks,           //              so
               | I'll punt on this for now and come back later when I wrap
               | my head           //              around the proper SQL.
               | //              we're not actually using this anywhere
               | just yet, so no biggie -\_(tsu)_/-
               | populatePeopleFromDatabase(people);       }
               | // ... some time later, Bob comes along and implements
               | the murderer execution logic:       const murderers:
               | Array<Murderer> = [];
               | populateMurderersFromDatabase(murderers);       // Bob is
               | about to have a really shitty day:
               | murderer.forEach((murderer) => murderer.kill());
               | 
               | It is not possible to write an analogous example in
               | Haskell using `head`.
        
               | mananaysiempre wrote:
               | > there's no accepted definition of what an unsound type
               | system is
               | 
               | Huh?
               | 
               | The cheeky answer would be that the definition here is
               | the one the TypeScript documentation itself uses[1].
               | 
               | The useful answer is that there's only one general
               | definition that I've ever encountered: a type system is
               | sound if no well-typed program encounters type errors
               | during its execution. Importantly, that's _not_ a
               | statement about the (static) type system in isolation:
               | it's tied to the language's dynamic semantics.
               | 
               | The tricky part, of course, is defining "type error". In
               | theoretical contexts, it's common to just not define any
               | evaluation rules at all for outwardly ill-typed things
               | (negating a list, say), thus the common phrasing that no
               | well-typed program must get stuck (unable to evaluate
               | further). In practical statically-typed languages, there
               | are on occasion cases that are defined not to be type
               | errors essentially by fiat, such as null pointer accesses
               | in Java, or escape hatches, such as unsafeCoerce in
               | practical implementations of Haskell.
               | 
               | Of course, ECMAScript just defines behaviour for
               | _everything_ (except violating invariants in proxy
               | handlers, in which case, lol, good luck), so arguably
               | every static type system for it is sound, even one that
               | allows var foo: string = 42. Obviously that's not a
               | helpful point of view. I think it's reasonable to say
               | that whatever we count as erroneous situations must at
               | the very least include all occurrences of ReferenceError
               | and TypeError.
               | 
               | TypeScript prevents most of them, which is good enough
               | for its linting use case, when the worst possible result
               | is that a buggy program crashes. It would definitely not
               | be good enough for Closure Compiler's minification use
               | case, when the worst possible result is that a correct
               | program gets silently miscompiled (misminified?).
               | 
               | [1] https://www.typescriptlang.org/docs/handbook/type-
               | compatibil...
        
               | RyanCavanaugh wrote:
               | Flow's type system isn't sound either FWIW
        
               | kevincox wrote:
               | > it could minify the properties declared as private,
               | while leaving the public ones intact.
               | 
               | I don't think it ever actually did this. It renamed all
               | properties (you could use the index syntax to avoid this)
               | and just used a global mapping to ensure that every
               | source property name was consistently renamed (no matter
               | what type it was on). I don't think type information was
               | ever actually used in minification.
               | 
               | So if you had two independent types that had a `getName`
               | function the compiler would always give them the same
               | minified name even though in theory their names could be
               | different because they were fully independent types. The
               | mapping was always bijective. This is suboptimal because
               | short names like `a` could only be used for a single
               | source name, leading to higher entropy names overall.
               | Additionally names from the JS runtime were globally
               | excluded from renaming. So any `.length` property would
               | never be renamed in case it was `[].length`.
        
               | AprilArcus wrote:
               | of course this created an interoperability nightmare with
               | third party libraries, which irrevocably forked Google's
               | whole JS ecosystem from the community's 20 years ago and
               | turned their codebases into a miserable backwater.
        
             | btown wrote:
             | Google's Closure Library is fascinating too. It's being
             | retired, but if you want to build a rich text interface for
             | email authoring that truly feels like Gmail, warts and all,
             | you can just use a pre-compiled version of the library and
             | follow https://github.com/google/closure-
             | library/blob/master/closur... within a more modern
             | codebase!
        
             | rty32 wrote:
             | Closure is almost a forgotten child of Google now. Does not
             | even fully support ES2022 as of today. We are working hard
             | to get rid of it completely. Surprise, lots of important
             | projects still rely on it today.
        
               | jazzypants wrote:
               | This is true. For instance, React still uses Closure
               | compiler in their build process.
        
           | simplify wrote:
           | Facebook never gave Flow enough resources, whereas Microsoft
           | has had 10+ devs on TypeScript for a long time.
        
             | sesm wrote:
             | Because Flow is an actual developer tool, not a rent-
             | seeking landgrab with a marketing budget.
        
               | 9dev wrote:
               | I don't know what axe you have to grind, but TypeScript
               | is firmly in the hands of the community now. There's not
               | much Microsoft could do to change that. In what way would
               | it be rent-seeking?
        
               | recursive wrote:
               | If you're paying rent for typescript, you're doing it
               | wrong.
        
           | hajile wrote:
           | Flow tries to be sound and that makes it infinitely better
           | than TS where the creators openly threw the idea of soundness
           | out the window from the very beginning.
        
             | machiaweliczny wrote:
             | But in practice is was crap
        
             | ahuth wrote:
             | TS made the choice to be "just JS" + types, and lean into
             | JS-isms.
             | 
             | Both choices are reasonable ones to make. Flow has some
             | really cool stuff, and works great for a lot of people.
             | 
             | There's no denying, though, that there's TS has done
             | something right (even if you personally dislike it)
        
             | idlephysicist wrote:
             | Can you explain what you mean when you say "to be sound"?
        
               | pansa2 wrote:
               | Here's an example of TypeScript failing to be sound - it
               | should give a type error but it doesn't. I believe Flow
               | does indeed give a type error in this situation:
               | 
               | https://news.ycombinator.com/item?id=41069695
        
               | recursive wrote:
               | You don't have to go even that far to find unsoundness in
               | flow.                   const arr = ["abcd"];
               | const str = arr[1];         const num = str.length; //
               | this throws         console.log(num);
               | 
               | For me, typescript is a pretty good balance.
        
               | fabiospampinato wrote:
               | Wait, so Flow is not actually sound and their website is
               | lying? Or do they have some "technically correct"
               | definition of "sound" that takes stuff like that into
               | account?
        
               | recursive wrote:
               | I have no idea about the lawyerly technicalities, but you
               | can try it yourself to verify what I'm saying.
               | 
               | https://flow.org/try/
               | 
               | Compare these two programs.                   const arr =
               | ["abcd"];         const str = arr[1];         const num =
               | str.length; // this throws at runtime              const
               | arr = [new Date];         const dt = arr[1];
               | const num = dt.length; // fails to type check
        
             | dwb wrote:
             | This is a point in Flow's favour. However! Seven years ago
             | or so, when TypeScript was quite young and seemed inferior
             | to Flow in almost all respects, I chose Flow for a large
             | project. Since then, I spent inordinate amounts of time
             | updating our code for the latest breaking Flow version,
             | until one came along that would have taken too long to
             | update for, so we just stayed on that one. We migrated to
             | TypeScript a little while back and the practical effect has
             | been much more and effective type checking through more
             | coverage and support. TypeScript may be unsound, but it
             | works better over all. We turn on the vast majority of the
             | safety features to mitigate the unsoundness. And it's
             | developed by a team that are beholden to a large and
             | vibrant user base, so any changes are generally well-
             | managed. There's no contest, really.
        
           | sesm wrote:
           | There was no real competition, Flow was a practical internal
           | tool with 0 marketing budget. Typescript is typical MS 3E
           | strategy with a huge budget. Needless to say, Flow is much
           | more practical and less intrusive, but marketing budget
           | captured all the newbie devs.
        
             | ignoramous wrote:
             | > _There was no real competition_
             | 
             | There was: _Anders Hejlsberg and Lars Bak: TypeScript,
             | JavaScript, and Dart_
             | https://www.youtube.com/watch?v=5AqbCQuK0gM (2013).
             | 
             | Summary: https://g.co/gemini/share/a60c3897bae1 /
             | https://archive.is/qJ1wA
        
             | com2kid wrote:
             | TypeScript was really _really_ easy to get started with
             | back in the day. It allows for incremental correctness, has
             | good docs, and good tooling. On top of that a lot of
             | beginner React tutorials started out with TypeScript, which
             | onboarded a lot of new engineers to the TS ecosystem, and
             | got them used to the niceties of TS (e.g. import syntax).
        
         | pphysch wrote:
         | > In Python, I've even heard of people writing types in source
         | code but never checking them
         | 
         | This is my main approach. Type hints are wonderful for keeping
         | code legible/sane without going into full static type
         | enforcement which can become cumbersome for rapid development.
        
           | josephg wrote:
           | You can configure typescript to make typing optional. With
           | that option set, you can literally rename .js files to .ts
           | and everything "compiles" and just works. Adding this feature
           | to nodejs means you don't even have to set up tsc if you
           | don't want to.
           | 
           | But if I were putting in type hints like this, I'd still
           | definitely want them to be statically checked. Its better to
           | have no types at all than _wrong_ types.
        
             | jaggederest wrote:
             | Yeah I start projects by explicitly typing `any` all over
             | the place and gradually refining things, so every type
             | that's specified is explicit and checked, I'm really
             | enjoying that style.
        
               | crabmusket wrote:
               | Combine this with an eslint config that nudges you about
               | explicit any, and the typescript compiler option to
               | disallow implicit any, and you're well taken care of.
        
             | pansa2 wrote:
             | > Its better to have no types at all than _wrong_ types.
             | 
             | I agree - but the type systems of both Python and
             | TypeScript are unsound, so all type hints can potentially
             | be wrong. That's one reason why I still mostly use untyped
             | Python - I don't think it's worth the effort of writing
             | type annotations if they're just going to sit there and
             | tell lies.
             | 
             | Or maybe the unsoundness is just a theoretical issue - are
             | incorrect type hints much of a problem in practice?
        
               | zoul wrote:
               | In my experience unsoundness is almost never a problem in
               | practice, see here for details:
               | 
               | https://effectivetypescript.com/2021/05/06/unsoundness/
        
               | hajile wrote:
               | Unsound types are never a problem until they are at which
               | point you are staring at code that SHOULD be working, but
               | is somehow breaking.
        
               | lolinder wrote:
               | I've been using TypeScript professionally for 6+ years
               | and have only ever run into issues at the border between
               | TypeScript and other systems (usually network, sometimes
               | libraries that don't come with types). There are a few
               | edge cases that I'm aware of, but they don't really come
               | up in practice.
        
               | kcrwfrd_ wrote:
               | Is this "unsound"-ness that you're referring to because
               | it uses structural typing and not nominal typing?
               | 
               | Fwiw I've been working with TypeScript for 8+ years now
               | and I'm pretty sure wrong type hints has never been a
               | problem. TS is a God-send for working with a codebase.
        
               | nyssos wrote:
               | There's not much connection. Typescript's record types
               | aren't sound, but that's far from its only source of
               | unsoundness, and sound structural typing is perfectly
               | possible.
        
               | lolinder wrote:
               | Soundness is also a highly theoretical issue that I've
               | never once heard a professional TypeScript developer
               | express concern about and have never once heard a single
               | anecdote of it being an issue in real-world code that
               | wasn't specifically designed to show the unsoundness. It
               | usually only comes up among PL people (who I count myself
               | among) who are extremely into the theory but not
               | regularly coding in the language.
               | 
               | Do you have an anecdote (just one!) of a case where
               | TypeScript's lack of type system soundness bit you on a
               | real application? Or an anecdote you can link to from
               | someone else?
        
               | kcrwfrd_ wrote:
               | Ah someone else posted a link and I understand the
               | unsoundness now.
               | 
               | The only time an issue ever came up for me was in dealing
               | with arrays                 let foo: number[] = [0, 1, 2]
               | // typed as number but it's really undefined       let
               | bar = foo[3]
               | 
               | But once you're aware of the caveat it's something you
               | can deal with, and it certainly doesn't negate the many
               | massive benefits that TS confers over vanilla JS.
        
               | lolinder wrote:
               | Yeah, that example is unsound in the same way that Java's
               | type system is unsound, it's a compromise nearly all
               | languages make to avoid forcing you to add checks when
               | you know what you're doing. That's not the kind of
               | problem that people usually are referring to when they
               | single out TypeScript.
        
               | nyssos wrote:
               | > Do you have an anecdote (just one!) of a case where
               | TypeScript's lack of type system soundness bit you on a
               | real application?
               | 
               | Sure. The usual Java-style variance nonsense is probably
               | the most common source, but I see you're not bothered by
               | that, so the next worst thing is likely object spreading.
               | Here's an anonymized version of something that cropped up
               | in code review earlier this week:                   const
               | incomingValue: { name: string, updatedAt: number } = {
               | name: "foo", updatedAt: 0 }              const
               | intermediateValueWithPoorlyChosenSignature: { name:
               | string } = incomingValue              const
               | outgoingValue: { name: string, updatedAt: string } = {
               | updatedAt: new Date().toISOString() ,
               | ...intermediateValueWithPoorlyChosenSignature }
        
               | lolinder wrote:
               | I mean... yes, there's a footgun there where you have to
               | know to spread first and _then_ add the new properties.
               | That 's just a good practice in the general case: an
               | intermediate type that fully described the data wouldn't
               | have saved you from overwriting it unless you actually
               | looked closely at the type signature.
               | 
               | And yes, TypeScript types are "at least these properties"
               | and not "exactly these properties". That is by design and
               | is frankly one reason why I _like_ TypeScript over Java
               | /C#/Kotlin.
               | 
               | I'd be very interested to know what you'd do to change
               | the type system here to catch this. Are you proposing
               | that types be exact bounds rather than lower bounds on
               | what an object contains?
        
               | cstrahan wrote:
               | No, TypeScript is not unsound because it uses structural
               | typing.
               | 
               | A language has a sound type system if every well-typed
               | program behaves as defined by the language's semantics
               | during execution.
               | 
               | Go is structurally typed, and yet it is sound: code that
               | successfully type checks is guaranteed to abide the
               | semantics of the language.
               | 
               | TypeScript is unsound because code that type checks does
               | _not_ necessarily abide the semantics of the language:
               | function messUpTheArray(arr: Array<string | number>):
               | void {           arr.push(3);       }              const
               | strings: Array<string> = ['foo', 'bar'];
               | messUpTheArray(strings);              const s: string =
               | strings[2];       console.log(s.toLowerCase())
               | 
               | `strings` is declared as a `Array<string>`, but
               | TypeScript is happy to insert a `number` into it. This is
               | a contradiction, and an example of unsoundness.
               | 
               | `s` is declared as `string`, but TypeScript is happy to
               | assign a `number` to it. This is a contradiction, and an
               | example of unsoundness.
               | 
               | This code eventually fails at runtime when we try to call
               | `s.toLowerCase()`, as `number` has no such function.
               | 
               | What we're seeing here is that TypeScript will readily
               | accept programs which violate its own rules. Any language
               | that does this, whether nominally typed or structurally
               | typed, is unsound.
        
             | black3r wrote:
             | Or you can configure the TS compiler to allow JS imports,
             | then everything also compiles and works, but you can slowly
             | convert your codebase from JS to TS file by file and be
             | sure that all TS files are properly typed and all JS files
             | are untyped instead of having everything as TS files where
             | some are typed and some are not.
        
           | pansa2 wrote:
           | With this approach, do you still use Python's standard syntax
           | for type hints?                   def mersenne(p: int):
           | return 2**p - 1
           | 
           | Or, given there's no need for the type hints to be checker-
           | friendly, do you make them more human-friendly, e.g:
           | def mersenne(p: 'prime number'): return 2**p - 1
        
           | Humphrey wrote:
           | Exactly. And if you use a library that does lots of meta
           | programming (like Django) then it's impossible to pass all
           | type errors. Hopefully one day the type system will be
           | powerful enough to write a Django project with passing tests.
        
           | edflsafoiewq wrote:
           | IME if you aren't checking them, they're eventually going to
           | be out of date.
        
           | rlt wrote:
           | I don't find TypeScript to be burdensome when rapidly
           | iterating. Depending on how you've configured your dev
           | environment you can just ignore type errors and still run the
           | code.
        
         | phartenfeller wrote:
         | There is an EcmaScript proposal to go in that direction:
         | https://github.com/tc39/proposal-type-annotations
         | 
         | I think this should be part of the language spec.
        
           | wiseowise wrote:
           | Beyond ugly. They should just make TS official and be done
           | with it.
           | 
           | E: I thought it was JSDoc proposal. Ignore the comment.
        
             | IshKebab wrote:
             | What do you mean ugly? This basically _is_ making
             | Typescript official.
             | 
             | They just can't have browsers doing the actual type
             | checking because there isn't a specification for how to do
             | that, and writing one would be extremely complicated, and
             | I'm not sure what the point would be anyway.
        
               | wiseowise wrote:
               | I misread the proposal, tho it it was for JSDoc.
        
             | padavanchik wrote:
             | There is no language spec for TS. No alternative
             | implementations. All we have is checker.ts. It's ugly and
             | slow.
        
             | blovescoffee wrote:
             | I did only briefly look at the proposal. What did you find
             | so ugly?
        
               | wiseowise wrote:
               | I misread the proposal. Thought it was for JSDoc.
        
               | meiraleal wrote:
               | Misread no, you didn't read.
        
               | wiseowise wrote:
               | Yeah. I saw JSDoc and closed it, lol.
        
               | Dylan16807 wrote:
               | Specifically, you saw the section titled "Limits of JSDoc
               | Type Annotations"?
        
               | wiseowise wrote:
               | Specifically, I saw JSDoc syntax and it triggered me so
               | much that I closed the page and threw my phone away in
               | disgust at absurdness of even the idea that someone
               | thought having something like this unironically is a
               | remotely good idea.
        
               | FractalHQ wrote:
               | I support this behavior as the only correct reaction.
        
         | Doxin wrote:
         | > In Python, I've even heard of people writing types in source
         | code but never checking them, essentially using type hints as a
         | more convenient syntax for comments.
         | 
         | Note that there's IDEs that'll use type hints to improve
         | autocomplete and the like too, so even when not checking types
         | it can make sense to add them in some places.
        
         | dobladov wrote:
         | You can have this now adding types with JSDoc and validating
         | them with typescript without compiling, you get faster builds
         | and code that works everywhere without magic or need to strip
         | anything else than comments.
         | 
         | The biggest pain point of using JSDoc at least for me was the
         | import syntax, this has changed since Typescript 5.5, and it's
         | now not an issue anymore.
        
           | murmansk wrote:
           | For god's sake, please stop shilling JSDoc as a TS
           | replacement. It is not. If you encounter anything more
           | complicated than `A extends B`, JSDoc is a pain in the ass of
           | huge intensity to write and maintain.
        
             | adhamsalama wrote:
             | You can write TypeScript types in JSDoc.
        
               | sureIy wrote:
               | You can't write complex TypeScript types in JSDoc, which
               | is what GP said.
               | 
               | The moment you need to declare or extend a type you're
               | done, you have to do so in a separate .ts file. It would
               | be _possible_ to do so and import it in JSDoc, but as
               | mentioned before it's a huge PITA on top of the PITA that
               | writing types can already be (e.g. function
               | /callbacks/generics)
        
             | dobladov wrote:
             | You should write complex types in interfaces files where
             | they belong, and there's full typescript support.
             | 
             | I use this approach professionally in teams with many
             | developers, and it works better for us than native TS.
             | Honestly give it a try, I was skeptical at first.
        
               | rty32 wrote:
               | In general JSDoc is just much more verbose and has more
               | friction, even outside complex types. I recently finished
               | a small (20 files/3000 lines), strictly typed JS project
               | using full JSDoc, and I really miss the experience of
               | using the real TypeScript syntax. Pain points: annotating
               | function parameter types (especially anonymous function),
               | intermediate variable type and automatic type-only
               | import, these are the ones that I can remember. Yes you
               | can get 99% there with JSDoc and .d.ts files, but that's
               | painful.
        
               | dobladov wrote:
               | I use snippets to write those, yes it's more verbose
               | there's not denying that.
               | 
               | For me the advantages of just having JS files and not
               | worrying about more complex source-maps, build files, etc
               | definitely makes it worth it.
        
               | FractalHQ wrote:
               | Source maps and build files are automatically generated
               | when bundling which you need to do with or without
               | typescript... so this argument always confuses me. There
               | is no tangible downside in my experience.. either way
               | it's just typing "pnpm build".
        
             | afavour wrote:
             | I've had a lot of success combining JSDoc JS with .d.ts
             | files. It's kind of a Frankenstein philosophically (one
             | half using TS and one half not) but the actual experience
             | is great: still a very robust type system but no
             | transpiling required.
             | 
             | In a world where ES modules are natively supported
             | everywhere it's a joy to have a project "just work" with
             | zero build steps. It's not worth it in a large project
             | where you're already using five other plugins in your build
             | script anyway but for small projects it's a breath of fresh
             | air.
        
               | flanbiscuit wrote:
               | I do this as well. JSDoc is great for simple definitions,
               | but as soon as you want to do something more complicated
               | (generics, operators, access types, etc) you get stuck.
               | The .d.ts are ignored because you're only importing them
               | within JSDoc comments.
        
             | Waterluvian wrote:
             | Jsdoc is honestly fine for simple and smaller projects. But
             | yeah, it's definitely not nearly as expensive while being
             | anywhere as succinct.
        
               | yard2010 wrote:
               | JSDoc is for docs, TypeScript is a static type checker.
               | How can these tools be used interchangeably?
        
             | tracker1 wrote:
             | JSDoc is also helpful in dealing with multiple argument
             | option types for a function or constructor, which won't
             | show in TS alone.
        
               | sroussey wrote:
               | You can do it in TS.
               | 
               | https://www.typescriptlang.org/docs/handbook/2/functions.
               | htm...
        
           | itsmeste wrote:
           | I strongly agree, but JSDoc isn't "the cool thing". So it's
           | left to be used by us, who care (and read their docs).
        
             | llimllib wrote:
             | The auto-export of declared types was what killed it for me
        
           | epolanski wrote:
           | JSDoc absolutely does not scale and allows for very limited
           | type programming.
           | 
           | It's fine on toy projects, and somewhat I would say, for 99%
           | of users that don't even know what a mapped or intersection
           | type is.
        
             | mablopoule wrote:
             | JSDoc does not scale, but some projects are just better
             | when they aren't scaled.
             | 
             | JSDoc is indeed fine on toy project, or in fact any project
             | (even prod-ready ones) that doesn't warrant the trouble of
             | adding NPM packages and transpilation steps.
             | 
             | Although they are rare, those type of small, feature-
             | complete codebases do exists.
        
         | black3r wrote:
         | > If Node.js can run TypeScript files directly, then the
         | TypeScript compiler won't need to strip types and convert to
         | JavaScript
         | 
         | Node.JS isn't the only JS runtime. You'll still have to compile
         | TS to JS for browsers until all the browsers can run TS
         | directly. Although some bundlers already do that by using a
         | non-official compiler, like SWC (the one Node's trying out for
         | this feature).
         | 
         | > In Python, I've even heard of people writing types in source
         | code but never checking them, essentially using type hints as a
         | more convenient syntax for comments.
         | 
         | It's not just comments. It's also, like the name "type hint"
         | suggests, a hint for your IDE to display better autocomplete
         | options.
        
           | pansa2 wrote:
           | > _It 's not just comments. It's also a hint for your IDE to
           | display better autocomplete options._
           | 
           | Ah yes, autocomplete is another benefit of machine-readable
           | type hints. OTOH there's an argument that another IDE
           | feature, informational pop-ups, would be better if they paid
           | more attention to comments and less to type hints:
           | 
           | https://discuss.python.org/t/a-more-useful-and-less-
           | divisive...
        
       | commercialnix wrote:
       | https://rescript-lang.org/
        
         | garbagepatch wrote:
         | Looks very similar to Reason ML, another language that compiles
         | to Js: https://reasonml.github.io/docs/en/getting-started
        
           | hajile wrote:
           | ReScript was an outgrowth of ReasonML and basically split the
           | community killing both of them.
        
             | mardifoufs wrote:
             | What was the reason behind the split?
        
       | storafrid wrote:
       | I have mixed feelings about this. While I do use TS with Node.js
       | today and absolutely like the concept, its type system is still
       | far from something mature and stable like C#. We keep running
       | into ceilings (EDIT: lack of completeness/depth, not lack of
       | complexity) all the time, and TypeScript questions on Stack
       | Overflow is basically a library of workarounds. Mostly bad ones.
       | So if I worked on Node.js I would prefer it to evolve more before
       | actually marrying and having kids with it. But at the same time,
       | I like the direction Node.js is taking.
        
         | Zamicol wrote:
         | Well said. Bearing that in mind, we've found that JSDoc is a
         | reasonable substitution for some TypeScript applications;
         | however, JSDoc has limitations that we've ran into frequently
         | as well.
        
         | coffeemug wrote:
         | What's an example of a ceiling? Out of all the mass-market
         | programming languages, TS arguably has the most advanced type
         | system in the world. It's a modern marvel that they got it
         | working on top of Javascript.
        
           | mdhb wrote:
           | I don't know what you mean here by advanced? If you mean the
           | sheer amount of fuckery they have to do in order to make it
           | work with JS perhaps you have a point.
           | 
           | If you mean expressiveness or consistent or soundness then
           | no, it's actually very bad compared to almost anything else
           | and I think the longer it goes on the more it starts to feel
           | like a house of cards.
           | 
           | The upside I guess is that whenever Safari decides to get
           | their shit together Web Assembly is well placed to get us out
           | of the scenario where we are forced to use JS and as an
           | extension Typescript at all for most things and actually good
           | language choices with reliable type systems like Dart, Kotlin
           | and C# all become viable options.
           | 
           | There is no way I'd choose JavaScript over those other
           | options in the majority of scenarios unless I was forced to.
        
             | wiseowise wrote:
             | > The upside I guess is that whenever Safari decides to get
             | their shit together Web Assembly is well placed to get us
             | out of the scenario where we are forced to use JS and as an
             | extension Typescript at all for most things and actually
             | good language choices with reliable type systems like Dart,
             | Kotlin and C# all become viable options.
             | 
             | Out of those three only Dart has nice DX story compared to
             | JS world.
        
           | bottlepalm wrote:
           | I think it took the seemingly impossible challenge of
           | bringing typing to a dynamic language that made typescript so
           | powerful in the first place.
           | 
           | All other static languages start bottom up, simple to more
           | complex, but end up getting boxed in by their own design.
           | TypeScript started top down, trying to map itself on to a
           | fully dynamic language. Never getting boxed in, just trying
           | to 'fill' the box that is all the possibilities of
           | JavaScript. 10 years on and TypeScript is still exciting,
           | making significant updates and improvements.
        
             | randomdata wrote:
             | Typescript isn't particularly powerful compared to other
             | _non-mainstream_ languages, though, which is why the parent
             | comment was careful to add that caveat. Which is to say
             | that I 'm not sure the idea that "all other static
             | languages" start simple and get boxed in stands up.
             | 
             | You may have a point that Typescript would have been
             | relegated to obscurity with all the others had it tried to
             | start "top down" as a brand new language. There may be some
             | truth that it is a necessity of a language to start simple
             | in order to become accepted in the mainstream and that
             | Typescript only made it because it rode on the coattails of
             | a language that also started simple: Javascript.
        
           | storafrid wrote:
           | Certainly advanced, but not mature in my experience. Using
           | e.g. classes and inferred generic function arguments, quickly
           | reveals a lot of features that are missing. Often some
           | similar feature is present but it lacks depth/completeness.
           | Lots of good discussions to read in TS repo on GitHub if
           | you're interested: Optional generic type inference, extends
           | oneof, generic values, keyof a subset, conditional types,
           | etc.
           | 
           | I want to emphasize that the reason we keep running into
           | "ceilings" is probably because of its advanced type system.
           | Libraries and frameworks are using those type features and
           | when we can't keep building on the type - we end up casting
           | to unknown and reconstructing it. Which feels worse than not
           | being able to construct that complex type at all.
        
         | SebastianKra wrote:
         | This is the first time I'm hearing such a claim.
         | 
         | In C# you can't work with optional generics because an optional
         | reference type is different from an optional value type.
         | 
         | C#s poor type-inference often requires you to type out types
         | thrice. You can't declare constants or class members with type-
         | inferrence.
         | 
         | The only way to define sum-types (A | B | C) is through
         | intefaces and I'm pretty sure they can't be sealed. Defining
         | product-types (A & B & C) is impossible.
        
           | storafrid wrote:
           | Sorry I probably used the wrong term, not a native English
           | speaker. I didn't mean lack of complexity or lack of
           | "features" but rather the lack of carefully thought-through
           | feature "depth". Like, we can infer generic arguments which
           | is nice, but then we try doing that with some keyof complex
           | type and it doesn't work. And later we find an issue on
           | GitHub saying that it's not implemented. Which is fine, I
           | love TS anyway and it's evolving.
        
           | fire_lake wrote:
           | C# has record (product) types now.
        
             | crabmusket wrote:
             | I'm not sure about the terminology here, but the & in TS is
             | much more than a record. You can use it to smush types
             | together e.g.
             | 
             | {name: string} & {birthday: Date}
             | 
             | becomes a single type with both properties.
        
               | fire_lake wrote:
               | Product types are tuple types.
               | 
               | Record types are tuple types with names instead of
               | indexes.
               | 
               | The TypeScript "&" is another thing.
        
       | rglover wrote:
       | Didn't expect types to come to JavaScript like this (native or
       | without a separate compiler), but I love the idea.
        
       | CodeCompost wrote:
       | Ok that's cool, but how about adding native support to browsers?
        
         | dimava wrote:
         | Stage 1
         | 
         | https://github.com/tc39/proposal-type-annotations
         | 
         | So maybe we'll have support in another five years
         | 
         | ... Or maybe we'll have "Support in another five years" in five
         | years, who knows
        
       | skybrian wrote:
       | It would be nice for debugging if at least simple npms could just
       | bundle their .ts files without any processing, so we could see
       | the comments and types as they existed in the git repo. Apps can
       | always minify them later.
       | 
       | (I use Deno, but also use some npms.)
        
         | flohofwoe wrote:
         | You can simply create npm packages which contain only the
         | 'unprocessed' TS source files (or really any type of files -
         | for instance I experimented with using npm as package for C/C++
         | projects in the past, it works just fine). Pre-bundling or
         | compiling from TS to JS is just a convention. And in case of
         | bundling not a good one IMHO, because bundling should only be a
         | final step in the top-level project. One good reason to compile
         | the package content to .js/.d.js/.map files is that the
         | resulting package is usable both in JS and TS projects.
        
           | skybrian wrote:
           | The nice thing about this change to Node.js (when it's no
           | longer experimental) is that you could just distribute .ts
           | files and JS projects could use them.
        
       | harshitaneja wrote:
       | I really enjoy typescript and have been yearning for a typescript
       | runtime but I can't help but laugh that I left java all those
       | years ago to finally seek something a lot closer to java.
       | 
       | I guess we all just wanted java with JIT, more feature rich type
       | system and gradual typing. Also for all the shortcomings of npm
       | ecosystem, it is a lot less daunting and more fun to be using
       | libraries in this ecosystem.
       | 
       | And surprisingly even though rust is on a different end of the
       | language spectrum but yet it offers a similar feel.
       | 
       | Edit: JIT was not the right terminology to use. I lazily wrote
       | JIT. Apologies. What I meant to convey was the difference in
       | startup times and run time between running something in JVM and
       | V8. Java feels heavy but in javascript ecosystem it feels so
       | nimble.
        
         | dagenix wrote:
         | Java does jit
        
           | harshitaneja wrote:
           | Yes, JIT was not the right terminology to use. I lazily wrote
           | JIT. Apologies. What I meant to convey was the difference in
           | startup times and run time between running something in JVM
           | and V8. Java feels heavy but in javascript ecosystem it feels
           | so nimble.
        
             | sgammon wrote:
             | Native Java via GraalVM starts up in milliseconds.
        
               | wiseowise wrote:
               | And it has to go through slow compilation step. With Node
               | you can have a cake and eat it too.
        
               | ZhongXina wrote:
               | You're saying it like it's an absolutely good thing. Some
               | (many?) users would rather pay the cost upfront in
               | compilation time (doesn't really matter if it's AOT or
               | JIT) than pay the same cost many times over through a
               | significantly slower runtime. JVM also scales up to
               | supercomputers (and everything in between) if you want it
               | to, so depending on your requirements a single-threaded
               | alternative might not even be an option.
        
               | wiseowise wrote:
               | I'll use C++ or Rust for such use cases.
        
               | sgammon wrote:
               | Okay!
        
               | DarkNova6 wrote:
               | You can't be serious about comparing the technological
               | capabilities of the JVM and Node and objectively declare
               | the latter as the winner.
               | 
               | Compilation times are also an absolute non-issue.
               | 
               | You don't compile for development. You do it for
               | production (in the rare circumstances that you need it).
        
               | harshitaneja wrote:
               | That's not what I am trying to convey here. JVM is
               | amazing and it is a feat that java is as fast as it is
               | and javascript and v8 are order of magnitude slower.
               | 
               | Also even though I also found java too verbose, I kept
               | believing that we need it to be so to write good
               | software. I still enjoy java but it doesn't compare to
               | the ergonomics of typescript for me. And nimbleness of
               | the experience according to me plays a decent role.
               | 
               | Currently for me, either I really care about performance
               | and I default to rust for those applications or I need
               | solutions where the product will evolve quickly over time
               | and I need great DX over performance and I default to
               | typescript for those.
               | 
               | Java definitely has a role to play but its role in my
               | work has certainly diminished.
        
               | sgammon wrote:
               | It does not "have" to go through such a step, by the way,
               | because you can simply run such code on the JVM.
        
         | bufferoverflow wrote:
         | Typescript is way better than Java, in my experience. It's a
         | lot less verbose. A lot more flexible.
        
           | sgammon wrote:
           | They are not comparable. If anything, Kotlin is the
           | equivalent in the JVM universe.
        
             | quonn wrote:
             | Kotlin is much closer to Java than to TypeScript even in
             | terms of flexibility.
        
               | DarkNova6 wrote:
               | To me "Flexibility" sounds a lot like "The programmer
               | always knows what he does".
        
               | scotty79 wrote:
               | Flexibility means for me more something more like, I
               | think I know what I want to do but I also know that I'm
               | probably wrong about that, so for now let's skip all the
               | baroque protocol and let me make it work first. Once I'm
               | sure I wrote what I actually wanted I'll add types if
               | only to get rid of some bugs, consider edge cases and
               | earn nice code completions and auto-generated docs.
        
               | sgammon wrote:
               | Sure, but Kotlin is to Java as TypeScript is to
               | JavaScript, which is the point I am making.
        
           | ZhongXina wrote:
           | Better for what? Quickly churning out short-lived code to get
           | the next round of funding, definitely. Writing (and
           | _supporting_) "serious" projects over the long term, which
           | also require high performance and/or high scalability, and
           | can rip through terabytes of data if needed, definitely not.
           | (All IMHO from lots of personal experience.)
        
             | viridian wrote:
             | Depends on your architecture. For scaling out rather than
             | up, node and python are both far more performant because
             | the footprint of minimum viable environment is much
             | smaller. When you need to serve anywhere from 10-200,000
             | requests a minute on the same system quickly, and
             | efficiently, lambda/azure functions/google app engine
             | backed by node or python is pretty ideal.
             | 
             | As an example, when my org needs to contact folks about
             | potential mass shooter events, our SLA is 90 seconds. If we
             | did it in cloud with java or .net, it'd be too slow to spin
             | up. If we did it on prem, we'd be charged insane amounts
             | just for the ability to instantly respond to low frequency
             | black swan events, or it'd be too slow. This is a real
             | story of how a Java dev team transitioned to using node for
             | scale in the first place.
        
               | neonsunset wrote:
               | Unlike Spring, JIT-based ASP.NET Core deployments spin up
               | very fast (<2-5s for even large-ish applications, the
               | main bottleneck is how fast it can open connections to
               | dependencies, load configuration, etc.). For AOT variant,
               | the startup time is usually below 200ms if we don't count
               | the slowness of surrounding infra which applies to any
               | language.
               | 
               | Of course CPU and RAM per request when compared to
               | Node.js are not even close as Node is easily slower by a
               | factor of 2-10.
        
             | hot_gril wrote:
             | It's good for things that don't involve ripping through
             | terabytes of data, which is actually a lot of things. And
             | idk if I'd use Java for that either.
        
               | mcluck wrote:
               | I'm actually in this exact position right now. The vast
               | majority of the time I write in TS but I have a need to
               | process a whole lot of data so I went for Rust instead.
               | Java is too much of a headache for me, personally
        
               | hot_gril wrote:
               | Yeah, Rust is fast, or you can go the other extreme with
               | Python if you can put the heavy lifting on native
               | modules.
        
         | bubblyworld wrote:
         | I'm very glad to use typescript over java, personally - the
         | ergonomics are so much better! Especially if you stray away
         | from the somewhat incomplete classes thing (type support for
         | decorator arguments isn't great, for instance) and just focus
         | on interfaces and functions.
         | 
         | One thing I miss that java has is runtime reflection of types
         | though. Typescript's ecosystem has a million different ways to
         | get around that and they're all a bit ugly imo.
        
         | zx8080 wrote:
         | > we all just wanted java with JIT, more feature rich type
         | system
         | 
         | Java has JIT. How is TypeSript type system feature-richer than
         | the Java one?
        
           | VMG wrote:
           | 1. *Type Inference*: TypeScript can automatically infer types
           | from context, reducing the need for explicit type
           | declarations. 2. *Union and Intersection Types*: Allows
           | combining multiple types, offering more flexibility in
           | defining data structures. 3. *Literal Types*: TypeScript
           | supports exact values as types (e.g., specific strings or
           | numbers), which can be useful for more precise type-checking.
           | 4. *Type Aliases*: You can create custom, reusable types,
           | enhancing code clarity and maintainability. 5. *Interfaces
           | and Structural Typing*: Interfaces allow for flexible
           | contracts, and TypeScript uses structural typing, where the
           | type compatibility is based on the shape of the data rather
           | than explicit type declarations. 6. *Mapped and Conditional
           | Types*: These allow for dynamic type creation and
           | manipulation, making the type system more powerful and
           | expressive. 7. *Optional Properties and Strict Null Checks*:
           | These provide better handling of undefined and null values.
        
             | tpm wrote:
             | That's just an copy-paste of some features, not a
             | comparison with Java which does most of that too.
        
               | afiori wrote:
               | Union types, structural typing, and conditional types are
               | like a big chunck of what makes typescript typescript.
               | 
               | It is how TS is able to "type" a completely untyped
               | language.
               | 
               | Just the support for union types is something that not
               | even Haskell or Ocaml have.
        
               | nequo wrote:
               | I am not familiar with TypeScript. Is there something
               | that you can achieve with union types that you can't with
               | sum types or type classes in Haskell?
        
               | afiori wrote:
               | TL;DR: Typescript is unsound so it can add a lot more
               | type-level features that would make a sound type system
               | undecidable
               | 
               | Conceptually no, almost every useful union type can be
               | easily converted to a sum type. In my opinion the
               | difference is in the ergonomics and in the implicit
               | structural subtyping.
               | 
               | For example a common union type is _number|string_ , and
               | the beatiful part is that to use a value of such a type
               | you do not need to do any matching or mapping you can
               | just use the value as it does not have a runtime wrapper,
               | for example _(x:string|number)= >JSON.stringify(x)_ works
               | perfectly fine.
               | 
               | Also you can have a function that takes as input a _Array
               | <string>|number|null_ and returns a string|number without
               | having to declare different contructors for the input
               | _number_ type and the output _number_ type
               | 
               | I believe that you can essentially implement this
               | behaviour by generating enough typeclasses in Haskell,
               | but regardless of the feasibility it, likely, would not
               | be a good idea.
               | 
               | An example of something in between union types an
               | Hindley-Milner sum types are Ocaml's polymorphic variants
               | types
               | https://ocaml.org/manual/5.2/types.html#sss:typexpr-
               | polyvar that are (I believe) more advanced than TS unions
               | but also a lot less ergonomic to use.
               | 
               | And TS has much more eg intersection types you could have
               | a function with type                   (x:number)=>string
               | & (x:string)=>number
               | 
               | meaning that it is _both_ a function that maps number to
               | strings and strings to numbers (again you can do this
               | with typeclasses but it is a worse experience)
               | 
               | typescript also has very good support for value types for
               | example there is the string type but also the "hello"
               | type which is the type of only the string "hello"
               | 
               | All in all if someone told me that they implemented
               | typescript in haskell typeclasses I would not call
               | bullshit on them, but I would not believe that anyone
               | would actually use it for anything
        
               | tpm wrote:
               | > For example a common union type is number|string
               | 
               | So that's like my beloved Perl then.
        
               | VMG wrote:
               | most of that? name one
        
               | tpm wrote:
               | Java has type inference. Also if a type alias is just a
               | new name for a existing type, then you can always do
               | something like                 class MyNewClass extends
               | OldClass {};
               | 
               | (of course it's not just a new name, it's also a new
               | class, but it's also still a OldClass, and you are out of
               | luck if OldClass is final or sealed)
               | 
               | Java also has interfaces, of course. And optional
               | properties (using Optional) and strict null checks, when
               | you want that, you can use it.
        
               | guipsp wrote:
               | Using optional still has the secret third thing problem
        
               | VMG wrote:
               | > type inference
               | 
               | very limited, for instance you must declare the type of a
               | public method
               | 
               | > alias
               | 
               | as you point out it's not
               | 
               | > Java also has interfaces, of course
               | 
               | but you have to implement them explicitly
               | 
               | > strict null checks, when you want that, you can use it
               | 
               | if we start accepting static analysis tools then C has
               | null checks as well I guess
        
               | tpm wrote:
               | > as you point out it's not
               | 
               | so what's the difference except the name?
               | 
               | > if we start accepting static analysis tools
               | 
               | I'm not talking about static analysis. In today's Java
               | you can write code that does not accept nulls, if you
               | want to.
        
               | svieira wrote:
               | You cannot write code that will _fail to compile_
               | `theEntryMethod(null)` unless you only use primitive
               | types. (You can, of course, make that method fail at
               | runtime, but that 's not what's being talked about here).
        
           | wiseowise wrote:
           | https://www.typescriptlang.org/docs/handbook/2/types-from-
           | ty...
           | 
           | https://www.typescriptlang.org/docs/handbook/2/template-
           | lite... alone puts TS over anything that Java has.
        
             | DarkNova6 wrote:
             | > alone puts TS over anything that Java has.
             | 
             | Virtual Threads alone challenge this assumption.
             | 
             | Syntax bloat is not a feature.
        
               | Byamarro wrote:
               | It's not really a syntax bloat, the linked docs mention
               | how to define strict string types and elaborate on type-
               | level programming, something that is a very rare and
               | powerful type-level capability. As far as I understand
               | Virtual Threads aren't type oriented feature, which is
               | basically the context for this thread.
        
               | 3836293648 wrote:
               | Virtual Threads are not a type system feature?
        
           | magnio wrote:
           | I don't use them directly much, but template literal generic
           | and contidiontal types is probably the closest a mainstream
           | language has inched towards dependent types.
           | 
           | Some examples of TypeScript power:
           | 
           | - SQL database in TypeScript types:
           | https://github.com/codemix/ts-sql
           | 
           | - Statically typed raw SQL queries:
           | https://github.com/andywer/squid?tab=readme-ov-file#tag-
           | func...
           | 
           | - (Someone fill in your TS hackery for me)
        
             | Vaguely2178 wrote:
             | There are various programming language interpreters that
             | run entirely in the type system:
             | 
             | - BF: https://github.com/susisu/typefuck
             | 
             | - Assembly: https://github.com/judehunter/ts-asm
        
           | yen223 wrote:
           | Java and Typescript have fundamentally different type
           | systems, that lead to drastically different ways to approach
           | types.
           | 
           | Utility types, like Partial<T>, are basically impossible to
           | represent in Java except with almost-duplicated classes.
        
             | tpm wrote:
             | > drastically different ways to approach types
             | 
             | Exactly.
             | 
             | > Partial<T>
             | 
             | Looking at that it's just what a default POJO (with
             | nullable properties) already is, so I'd see no need to
             | represent that in Java.
             | 
             | Looks cool though and I like Typescript; my issue with it
             | is that it needs transpiling to run. If it was a first-
             | class citizen in an environment I would use it for my pet
             | projects.
        
               | crabmusket wrote:
               | > it's just what a default POJO (with nullable
               | properties) already is
               | 
               | I think you missed the point. Partial<T> is an example of
               | a "mapped type", see the handbook for more explanation:
               | https://www.typescriptlang.org/docs/handbook/2/mapped-
               | types....
        
               | tpm wrote:
               | I understand that much, just thinking aloud what problem
               | would that solve in Java.
        
               | scotty79 wrote:
               | I think it's for when you need type that expresses
               | partial data update for an object that has some fields
               | required.
        
               | svieira wrote:
               | Yep - all non-primitive types in Java are `TheType |
               | null` - TypeScript actually allows you to strip out the
               | `| null`, which then means that sometimes you want to add
               | it back in. So Java doesn't have a need for `Partial<T>`,
               | it has a need for `NonNull<T>` and it can't express that
               | at the type system level very easily right now (you can
               | do it with type tagging and runtime checks inserted
               | explicitly, but it's not very ergonomic right now)
               | 
               | https://gist.github.com/svieira/9f8beeafb7bf4aa55d40c6385
               | 32f...
        
         | ninepoints wrote:
         | Not having an opaque tech stack encumbered by a patent
         | minefield is another plus.
        
         | qalmakka wrote:
         | > we all just wanted java with JIT
         | 
         | Java was literally the thing that made the term "JIT" popular,
         | so I really don't know what you were going for here.
         | 
         | Also I just can't see how Typescript is in any way "closer" to
         | Java - it's incredibly different IMHO. The only thing they have
         | in common is probably the "Javascript" misnomer and the fact
         | both support imperative programming, but that's it.
        
           | seanmcdirmid wrote:
           | Typescript's optional and unsound type system also does
           | nothing for a JIT beyond what it could already do for
           | JavaScript, you can't do optimization if your types are
           | unreliable. However, I really really like how Typescript's
           | type system super charges developer productivity (type errors
           | via the compiler and feedback via the IDE), and don't mind
           | this part of the design at all.
        
             | teaearlgraycold wrote:
             | You can use typescript types to compile functions. You just
             | might need to deoptimize when you actually hit the
             | function.
        
         | 38 wrote:
         | > gradual typing
         | 
         | AKA dynamic typing. Unless it's 100% static, it's dynamic
        
           | debugnik wrote:
           | Gradual typing could still keep some static guarantees if the
           | static part were sound, e.g. you couldn't assign a dynamic-
           | typed integer to a string-typed variable without checking the
           | type at runtime first; which TypeScript isn't.
           | 
           | Elixir's new type system does much better here, as it
           | determines whether a function actually guards for the right
           | type at runtime ("strong arrows") and propagates the
           | guarantees, or lack thereof, accordingly.
        
         | wiseowise wrote:
         | > Also for all the shortcomings of npm ecosystem, it is a lot
         | less daunting and more fun to be using libraries in this
         | ecosystem.
         | 
         | God I wish they'd just integrate something lightweight like npm
         | into JDK.
         | 
         | It is beyond me why you have to install third-party heavy
         | weight tool just to manage dependencies.
        
         | jddj wrote:
         | I'm somewhere here as well. Personally I think what I want is
         | the stdlib (without the current legacy/ all but deprecated
         | bits) and ecosystem of c# but with the ease and power of
         | structural algebraic types. AoT is fine, with option for single
         | binary. Ideally runtimeless with clever trimming. If it also
         | ran jitted in the browser all the better.
         | 
         | I also want compiler/type checker niceties like exhaustive
         | pattern matching.
        
         | tomjen3 wrote:
         | The typesystem of Java was so laughably unpowerful that it
         | severely constrained what you could write.
         | 
         | In Typescript you have far more freedom, and all the benefits
         | of strong types.
        
           | DarkNova6 wrote:
           | Strong types without strong typing that is.
        
           | yen223 wrote:
           | The fact that Java forced you to write types, and then made
           | everything implicitly nullable so that you still get
           | NullPointerExceptions at runtime after writing out all those
           | types, was probably a big reason why dynamically-typed
           | languages became popular.
        
         | lmm wrote:
         | Java's type system was just very limited, gradual typing is a
         | poor tradeoff most of the time. I used to think there were
         | advantages to something like Python, but once I found Scala I
         | never went back.
        
         | scotty79 wrote:
         | Gradual typing is the key. The problem with Java is that types
         | are in your face way before you actually need them.
         | 
         | With TS you can prototype with JS and only after you know what
         | you are looking for you can start to add types to find bugs and
         | edge cases and want to get nice code completions for your
         | stuff.
        
         | hot_gril wrote:
         | The type system is a big part of what made Java cumbersome.
         | It's loosened up a little over the years. TS itself may allow
         | partial typing, but when team/company policies are involved,
         | you'll often end up being forced to type everything.
        
       | throw156754228 wrote:
       | I see it just strips the typings. So if I attach the debugger I'm
       | still going to see javascript right?
        
         | zarzavat wrote:
         | Presumably it would also generate a source map to allow
         | debuggers to work properly, like tsc does.
        
       | zarzavat wrote:
       | One thing to note is that it is impossible to strip types from
       | TypeScript without a grammar of TypeScript. Stripping types is
       | not a token-level operation, and the TypeScript grammar is
       | changing all the time.
       | 
       | Consider for example: `foo < bar & baz > ( x )`. In TypeScript
       | 1.5 this parsed as (foo<bar) & (baz > (x)) because bar&baz wasn't
       | a valid type expression yet. When the type intersection operator
       | was added, the parse changed to foo<(bar & baz)>(x) which
       | desugared to foo(x). I realise I'm going back in time here but
       | it's a nice simple example.
       | 
       | If you want to continue to use new TypeScript features you are
       | going to need to keep compiling to JS, or else keep your node
       | version up to date. For people who like to stick on node LTS
       | releases this may be an unacceptable compromise.
        
         | spoiler wrote:
         | It's possible that internal SWC version will be versioned
         | alongside Node, meaning TS syntax support won't drift. Or am I
         | missing something?
        
           | thecopy wrote:
           | TypeScript evolves independent of Node, and the syntax you
           | can use depends on your `typescript` version in the
           | `package.json`
        
             | re-thc wrote:
             | Not if SWC or your tooling doesn't support it.
        
           | satanacchio wrote:
           | yes but can also be upgraded separately as npm package
        
         | the_gipsy wrote:
         | You would also have to update your compiler. I guess you could
         | phrase this as: you can't update your TS versions independently
         | from your node.js version. But that's probably not an issue.
        
           | zarzavat wrote:
           | It's an issue because node has a system of LTS releases,
           | whereas TypeScript has quarterly updates, so the release
           | cadence is different.
           | 
           | Updating node is much more fraught than updating TypeScript.
           | For example, it may break any native code modules. That's why
           | users are directed to use the LTS and not the most recent
           | release, so that there's enough time for libraries to add
           | support for the new version.
           | 
           | On the other hand, I usually adopt a new TypeScript version
           | as soon as it comes out.
        
             | another-dave wrote:
             | Though I'd primarily see this as a feature for the REPL or
             | manual scripts where I'm not going to mind doing a `nvm use
             | X`.
             | 
             | For production use, I'd still put my TS files through a
             | build pipeline as normal
        
               | chrisweekly wrote:
               | tangential protip: if you're using nvm to manage node
               | versions, take a look at fnm as a superior replacement.
               | (It can read the same .nvmrc file to switch on cd into a
               | given dir, but it's faster and "cleaner" wrt impact on
               | your shell.)
        
             | satanacchio wrote:
             | I made it sure to decouple the transpiler from node itself,
             | the transpiler is in a npm package called amaro, that is
             | bundled in node. The goal is to allow user to upgrade amaro
             | indipendently so we dont have to lock a ts version for the
             | whole lifespan of a release
        
             | mort96 wrote:
             | TypeScript feels "boring" enough at this point that being a
             | few years behind isn't gonna be an issue in most cases. For
             | teams who want to stay on the absolute latest release of
             | TypeScript but want to be more conservative with their Node
             | version, external compilation will remain necessary; but
             | for someone like me, where TypeScript has been "good
             | enough" for many years that I'm not excited by new
             | TypeScript releases, this feature will be really nice.
             | 
             | ("Boring" in this context is a compliment, by the way)
             | 
             | EDIT: Though reading other comments, it seems like you can
             | update the typescript stripper independent of node? That
             | makes this moot anyway
        
               | mu53 wrote:
               | typescript is still evolving in dramatic ways. The 5.0
               | release has some really good improvements
        
               | mort96 wrote:
               | But at the same time, it's good enough and has been good
               | enough for many years. It's like how I'm sure EcmaScript
               | 2024 contains cool new stuff, but if node only supported
               | ES6, I would have no trouble writing ES6.
        
           | klodolph wrote:
           | Not necessarily.
           | 
           | With a couple exceptions (like enums), you can strip the
           | types out of TypeScript and end up with valid JS. What you
           | _could_ do is stabilize the grammar, and release new versions
           | of TypeScript using the same grammar. Maybe you need a flag
           | to use LTS grammar in your tsconfig.json file.
        
         | Tade0 wrote:
         | I'm not worried about that too much to be honest.
         | 
         | To me beyond v4.4 or so, when it started being possible to
         | create crazy recursive dependent types (the syntax was there
         | since ~4.1 - it's just that the compiler complained), there
         | weren't a lot of groundbreaking new features being added, so
         | unless an external library requires a specific TS version to
         | parse its type declarations, it doesn't change much.
        
           | 3np wrote:
           | > crazy recursive dependent types
           | 
           | Some edge-cases involving those have bugfixes and ergonomy
           | improvents I've run into on 5.x.
        
         | noname120 wrote:
         | It's already the case for ECMAScript and I don't see why
         | TypeScript should be treated differently when Node.js has to
         | transpile it to JavaScript and among other things ensure that
         | there are no regressions that would break existing code.
         | 
         | Unlike Python typing it's not only type erasure: enums,
         | namespaces, decorators, access modifiers, helper functions and
         | so on need to be transformed into their JavaScript equivalent.
        
         | madeofpalk wrote:
         | It looks like the team has already considered this in one
         | regard
         | 
         | > _There is already a precedent for something that Node.js
         | support, that can be upgraded seperately, its NPM. Node bundles
         | a version of npm that can upgraded separately, we could do the
         | same with our TypeScript transpiler._
         | 
         | > _We could create a package that we bundle but that can also
         | be downloaded from NPM, keep a stable version in core, but if
         | TypeScript releases new features that we don 't support or
         | breaking changes, or users want to use the new shiny
         | experimental feature, they can upgrade it separately. This
         | ensures that users are not locked, but also provides support
         | for a TypeScript version for the whole 3 years of the lifetime
         | of Node.js release._
         | 
         | https://github.com/nodejs/loaders/issues/217
        
           | SomeCallMeTim wrote:
           | As long as Node understands to use the project-specific
           | version of TypeScript (i.e., the one in node_modules or the
           | PNP equivalent), that should be fine.
           | 
           | But it would be a step backward to need to globally upgrade
           | TypeScript (as you do with npm), since some older projects
           | will _not_ be compatible with newer versions of TypeScript.
           | 
           | Ask me how I know. ;)
        
             | silverwind wrote:
             | > As long as Node understands to use the project-specific
             | version of TypeScript
             | 
             | It won't, but in such a scenario, typescript would only be
             | a type checker, wich is a entirely different endeavor than
             | running typescript.
        
         | getcrunk wrote:
         | Do you really need to update all the time? Are the new features
         | always that immediately important?
        
         | nialv7 wrote:
         | Using inequality signs as angled brackets really is a mistake
         | isn't it...
        
           | klodolph wrote:
           | I'll flip this around... reusing comparison as angle brackets
           | is the mistake. C++ ran into some issues too.
           | 
           | I think Rust made the really smart move of putting :: before
           | any type parameters for functions. Go made the good move of
           | using square brackets for type parameters.
        
             | zarzavat wrote:
             | The problem can be traced back to ASCII/typewriters only
             | including three sets of paired characters, plus inequality
             | signs, which is not enough for programming languages.
             | 
             | We really need five sets: grouping, arrays/indexing,
             | records, type parameters, and compound statements. Curly
             | braces {} are also overloaded in JS for records and
             | compound statements, leading to x => {} and x => ({})
             | meaning different things.
             | 
             | Square brackets wouldn't work for parametric functions
             | because f[T](x) already means get the element at index T
             | and call it.
        
               | xigoi wrote:
               | I think the D syntax would work: f!T(x)
        
               | behnamoh wrote:
               | Everytime a standardization happens, part of human
               | creativity gets suppressed. Before ASCII, people were
               | inventing all sorts of symbols and even the alphabet was
               | flexible to changes. After ASCII, we got stuck with a
               | certain set of letters and symbols. Heck, even our
               | keyboards haven't changed that much since then. I really
               | think we need more symbols than just
               | &@$#%^*}{][<>()/\\_~|
        
               | parasense wrote:
               | Paired characters...
               | 
               | That's an interesting topic. Do you happen to know if
               | UTF-8 contains more "pair" characters? In Latex we call
               | these delimiteres, but that's just my limited experience
               | coming in from math side. I tend to agree that it would
               | be helpful to have more kind of
               | nesting/pairing/grouping/delimiting characters. The
               | problem is my imagination is limited to what I know from
               | the ASCII world, and so it goes... no idea what new sets
               | would look like.
        
               | pshc wrote:
               | So many different pairs are available. I like Asian
               | corner brackets [] and French guillemets << >>. The angle
               | brackets <>  are popular in CS/math papers I think,
               | though they might be confused with <>.
        
               | IshKebab wrote:
               | Sure, you can use Canadian Aboriginal Syllabics!
               | 
               | https://www.reddit.com/r/rust/comments/5penft/comment/dcs
               | q64...
        
               | klodolph wrote:
               | Five sets, but at any given place in the syntax, not all
               | five are possible. (I would add function calls to the
               | list--so, six.)
               | 
               | In most languages, (grouping and compound statements)
               | cannot syntactically appear in the same place as
               | (indexing, records, type parameters, function calls). So
               | we are immediately down to four.
               | 
               | Rust takes the approach that you use :: before type
               | parameters, so they are easily distinguished from
               | comparison operators at a syntactic level.
               | 
               | Go takes the approach that [] is just fine for type
               | parameters--which seems pretty reasonable to me. In Go,
               | there's nothing that can be both indexed *and* take a
               | type parameter.
        
             | lolinder wrote:
             | I don't think you're flipping it around, I think that's
             | exactly what OP was saying, just clearer.
        
           | jmull wrote:
           | Mistake isn't the right word. It's just a tradeoff.
           | 
           | There was no perfect solution available, so a tradeoff was
           | necessary. You can disagree with this particular tradeoff,
           | but had they gone another way some people would disagree with
           | that as well. To be a mistake there would have had to have
           | been an option available that was clearly better at the time.
           | 
           | Anyway, the idea that TS 5 should be backwards compatible
           | with TS 1 is probably a bad one. Personally, I think packages
           | with wide usage break backwards compatibility _far_ too
           | easily -- it puts everyone who uses it on an upgrade
           | treadmill, so it should be done _very_ judiciously. But even
           | I wouldn 't argue that TS 1 should have been its final form.
        
           | SomeCallMeTim wrote:
           | It's not a TypeScript mistake.
           | 
           | You could argue that it was a C++ mistake. It makes parsing
           | harder, but otherwise seems to work as expected, so I don't
           | consider it a mistake, but you could at least argue that way.
           | 
           | But regardless if it was a mistake in C++, it's now a
           | complete standard, used in C++, Java, C#, and other languages
           | to denote type parameters.
           | 
           | I would argue that it would have been a mistake to break that
           | standard. What would you have used, and in what way would
           | that have been enough better to compensate for the increased
           | difficulty in understanding TypeScript generics for users of
           | almost every other popular language?
        
             | vips7L wrote:
             | It's definitely the right choice for Typescript. You could
             | have gone the Scala route and used [] for generics, but
             | that is so heavily used in ts/js as arrays it would not
             | have made any sense.
        
         | WorldMaker wrote:
         | The syntax from the perspective of type _stripping_ has been
         | relatively stable for more versions of Typescript than it was
         | unstable. You had to reach all the way back to 1.5 in part
         | because it 's been very stable since about 2.x. The last major
         | shift in syntax was probably Conditional Types in 2.8 adding
         | the ternary if operator in type positions. (The type _model_ if
         | you were to try to typecheck rather than just type-strip has
         | changed a lot since 2.x, but syntax has been generally stable.
         | That 's where most of Typescript's innovation has been in the
         | type model/type inferencing rather than in syntax.)
         | 
         | It's still just (early in the process) Stage 1, but the
         | majority of Typescript's type syntax, for the purposes of type
         | stripping (not type checking), _is_ attempting to be somewhat
         | standardized: https://github.com/tc39/proposal-type-annotations
        
           | teaearlgraycold wrote:
           | They did _just_ add a new keyword, satisfies, in 5.4. That
           | would be a breaking change if you can't upgrade the type
           | stripper separately.
        
             | panzi wrote:
             | But at least its a loud failure and not a silent different
             | interpretation of the source as the example was. Still.
        
             | felixfbecker wrote:
             | This is true, but in other cases they added keywords in
             | ways that could work with type stripping. For example, the
             | `as` keyword for casts has existed for a long time, and
             | type stripping could strip everything after the `as`
             | keyword with a minimal grammar.
             | 
             | When TypeScript added const declarations, they added it as
             | `as const` so a type stripping could have still worked
             | depending on how loosely it is implemented.
             | 
             | I think there is a world where type stripping exists (which
             | the TS team has been in favor of) and the TS team might
             | consider how it affects type stripping in future language
             | design. For example, the `satisfies` keyword could have
             | also been added by piggy-backing on the `as` keyword, like:
             | const foo = { bar: 1 } as subtype of Foo
             | 
             | (I think not using `as` is a better fit semantically but
             | this could be a trade-off to make for better type stripping
             | backwards compatibility)
        
               | Timon3 wrote:
               | I don't know a lot about parser theory, and would love to
               | learn more about ways to make parsing resilient in cases
               | like this one. Simple cases like "ignore rest of line"
               | make sense to me, but I'm unsure about "adversarial"
               | examples (in the sense that they are meant to beat simple
               | heuristics). Would you mind explaining how e.g. your `as`
               | stripping could work for one specific adversarial
               | example?                   function foo<T>() {
               | return bar(                 null as unknown as T extends
               | boolean                 ? true /* ): */                 :
               | (T extends string                     ? "string"
               | : false                 )                 )         }
               | function bar(value: any): void {}
               | 
               | Any solution I can come up with suffers from at least one
               | of these issues:
               | 
               | - "ignore rest of line" will either fail or lead to
               | incorrect results - "find matching parenthesis" would
               | have to parse comments inside types (probably doable, but
               | could break with future TS additions) - "try finding end
               | of non-JS code" will inevitably trip up in some
               | situations, and can get very expensive
               | 
               | I'd love a rough outline or links/pointers, if you can
               | find the time!
               | 
               | [0] TS Playground link: https://www.typescriptlang.org/pl
               | ay/?#code/AQ4MwVwOwYwFwJYHs...
        
               | WorldMaker wrote:
               | Most parsers don't actually work with "lines" as a unit,
               | those are for user-formatting. Generally the sort of
               | building blocks you are looking for are more along the
               | lines of "until end of expression" or "until end of
               | statement". What defines an "expression" or a "statement"
               | can be very complex depending on the parser and the
               | language you are trying to parse.
               | 
               | In JS, because it is a fun example, "end of statement" is
               | defined in large part by Automatic Semicolon Insertion
               | (ASI), whether or not semicolons even exist in the source
               | input. (Even if you use semicolons regularly in JS, JS
               | will still insert its own semicolons. Semicolons don't
               | protect you from ASI.) ASI is also a useful example
               | because it is an ancient example of a language design
               | intentionally trying to be resilient. Some older JS
               | parsers even would ignore bad statements and continue on
               | the next statement based on ASI determined statement
               | break. We generally like our JS to be much more strict
               | than that today, but early JS was originally built to be
               | a resilient language in some interesting ways.
               | 
               | One place to dive into that directly (in the middle of a
               | deeper context of JS parser theory):
               | https://developer.mozilla.org/en-
               | US/docs/Web/JavaScript/Refe...
        
               | Timon3 wrote:
               | Thanks for the response, but I'm aware of the basics. My
               | question is pointed towards making language parsers
               | resilient towards separately-evolving standards. How
               | would you build a JS parser so that it correctly parses
               | any new TS syntax, without changing behavior of valid
               | code?
               | 
               | The example snippet I added is designed to violate the
               | rules I could come up with. I'd specifically like to
               | know: what are better rules to solve this specific case?
        
         | felixfbecker wrote:
         | I think the kind of teams that always stay on top of the latest
         | TypeScript version and use the latest language features are
         | also more likely to always stay on top of the latest Node
         | versions. In my experience TypeScript upgrades actually more
         | often need migrations/fixes for new errors than Node upgrades.
         | Teams that don't care about latest V8 and Node features and
         | always stay on LTS probably also care less about the latest and
         | greatest TypeScript features.
        
           | jitl wrote:
           | I work on a large app that's both client & server typescript
           | called Notion.
           | 
           | We find Typescript much easier to upgrade than Node. New Node
           | versions change performance characteristics of the app at
           | runtime, and sometimes regress complex features like async
           | hooks or have memory leaks. We tend to have multi-week
           | rollout plans for new Node versions with side-by-side deploys
           | to check metrics.
           | 
           | Typescript on the other hand someone can upgrade in a single
           | PR, and once you get the types to check, you're done and you
           | merge. We just got to the latest TS version last week.
        
         | js4ever wrote:
         | If only typescript could avoid changing syntax every 2 weeks.
        
       | sgammon wrote:
       | Really glad to see this
        
       | alabhyajindal wrote:
       | What next? Renaming Node.js to Node.ts?
       | 
       | I understand that built in TS support is very nice as provided by
       | Bun. But I feel doing this in Node is going to take a long time.
        
       | gaptoothclan wrote:
       | A long time ago I started converted to using node js for backend
       | work, seemed to offer many benefits over writing code in PHP
       | without bringing many problems of Java. I found node to be
       | somewhat clunky and a language where you had to bolt it together
       | to get the language you wanted. Eventually started writing golang
       | and it felt much easier to write, sometimes way more verbose but
       | the type safety just made coding simpler.
       | 
       | Typescript seemed like a good option but was just another bolt
       | on, I am not sure what value you gain by using Typescript over
       | Golang, you have nice defined types which is great but it does
       | not solve other issues with the language that are resolved in
       | golang (also solved in deno).
       | 
       | One large benefit of using node over golang is the speed of
       | prototyping something which I think having to use type script
       | largely negates, so I can not really decide if this is a good
       | step forwards or is making node loose some qualities that made it
       | a good choice in other ways.
        
         | _joel wrote:
         | I guess if you already know Javascript, or have inhouse
         | experience vs. learning Go. We use it with cdktf as previous fe
         | experience, seemed logical vs. Go
        
           | gaptoothclan wrote:
           | sorry was going to add that there are probably more
           | javascript developers in the jobs market, although there is a
           | limit to the usefulness of these developers.
           | 
           | In the company I worked at we were fairly small and did not
           | have huge applications running on node, so it made that
           | journey easier
        
         | __alias wrote:
         | I mean the obvious answer is language familiarity, If your
         | projects frontend code is in javascript/typescript ( which it
         | is ), then using node is an easy choice. Shared libraries,
         | shared types, etc etc
        
           | fulafel wrote:
           | Lots of people do of course use other languages for the
           | frontend. (Or go for thin frontends, ala HTMX )
        
           | gaptoothclan wrote:
           | I was in the paradigm, there was very little code reuse from
           | front to backend, some time performing validation I would
           | like to have that option, but I would not have that as a
           | killer feature that determined the language I use.
        
         | bezier-curve wrote:
         | Typescript is safer JS. You're still using JS with TS. The
         | "bolted on" phrasing makes me think your issue may be more the
         | absence of more opinionated frameworks like Django, that manage
         | everything out of the box. I love using Django, but it's a
         | little harder to go off the beaten path with it.
        
           | gaptoothclan wrote:
           | My phrasing there was a direct comparison of developer
           | experience between golang and nodejs. Golang has a very
           | complete core library, I try to avoid frameworks as much as
           | possible. For me I rarely have to think about the language or
           | ecosystem, everything I want or need is already part of the
           | language, testing, linting are some great examples
        
           | hot_gril wrote:
           | "Bolted on" is how I'd describe it too. Using TS means
           | messing a lot more with random config files. And standard
           | tools like the NodeJS profiler don't work with TS, which
           | hopefully will change soon.
           | 
           | I've never used Django. Express seems a lot nicer.
        
       | satanacchio wrote:
       | Hi I'm the author of the PR, AMA
        
         | mostafah wrote:
         | Thank you a lot. Great work. I know it's still experimental,
         | but over time it will have a big impact on developer experience
         | and will simplify the development workflow for a lot of
         | projects.
        
         | Shacklz wrote:
         | Great work, many thanks!
         | 
         | Out of curiosity, what do you see as next steps, and what
         | possible futures do you see for typescript in the node- and
         | overall JS-ecosystem?
        
           | satanacchio wrote:
           | this is the roadmap
           | https://github.com/nodejs/loaders/issues/217. We talked with
           | the typescript team and we will give each other continous
           | feedback on the progression. We made sure to take some
           | precautions in order to avoid breaking the ecosystem. I still
           | think in production, js is the way to go, so users should
           | always transpile their ts files.
        
       | BiteCode_dev wrote:
       | Eventually, node might allow JS to introspect those types.
       | 
       | That would be a huge win. Right now in Python, great tools like
       | pydantic exist because Python can introspect said types, and
       | generate checks out of them.
       | 
       | This mean you can define simple types, and get:
       | 
       | - type checking - run time data check - api generation - api
       | document generation
       | 
       | Out of a single, standard notation.
       | 
       | Right now in JS, things like zod have to do:
       | const mySchema = z.string();
       | 
       | Which is basically reinventing what typescript is already doing.
        
         | aitchnyu wrote:
         | Does this mean Node can know if an exception is subclass of
         | ValueError or an object is instance of SomeClass? I'm a TS
         | newb, I thought types outside of array, object, number, string
         | arent present in JS and Zod and typeguard functions return
         | plain objects with "trust me bro".
        
           | LelouBil wrote:
           | You are right, they aren't. In the JavaScript languages which
           | is what gets actually executed, there are no typescript
           | types.
           | 
           | The parent commenter was talking about a way for nodejs to
           | provide, via an API, the content of type annotations on
           | fields/functions/variables like in python.
           | 
           | However, in python the type annotations are a property of the
           | object at run time, whereas they are completely stripped
           | before execution for typescript.
           | 
           | So I'm not sure how it would work except by changing the
           | typescript philosophy of "not changing runtime execution"
        
           | gampleman wrote:
           | In JS, classes do retain runtime information. So the
           | `instanceof` is a real runtime operator that works by
           | checking the prototype chain of an object. So checking
           | subclasses can be done at runtime.
           | 
           | However, in TS other type information is erased at compile
           | time. So if you write                   type Foo = "a" | "b";
           | 
           | the runtime code will see that just as a plain string.
        
         | bythreads wrote:
         | That's not entirely true. `z.string()` in Zod offers more than
         | just type safety akin to TypeScript. TypeScript provides
         | compile-time type checking, while Zod adds runtime validation
         | and parsing.
         | 
         | For those unfamiliar:
         | 
         | `z.string()` effectively converts `mySchema` into a functional
         | schema capable of parsing and validation.
         | 
         | For example:
         | 
         | `mySchema.parse("some data")` returns successfully.
         | 
         | `mySchema.parse(321)` throws an exception.
         | 
         | I've used it in places where you need runtime validation and in
         | process verification - it works pretty well for that and you
         | can extract the types from it via :
         | 
         | const A = z.string(); type A = z.infer<typeof A>; // string
         | 
         | Meaning if you define your types in zod first, and infer their
         | types from that you get compile and runtime type checking.
         | 
         | ---
         | 
         | It a bit of an overkill for nimble and fast code bases though -
         | but works wonders for situations where in process proofing
         | needs to be done, and in all honesty it isn't that big of a
         | task to do this.
        
           | Dylan16807 wrote:
           | > Zod offers more than just type safety akin to TypeScript.
           | TypeScript provides compile-time type checking, while Zod
           | adds runtime validation and parsing.
           | 
           | Well of course it offers more, or you wouldn't be installing
           | a library.
           | 
           | The problem is that even when you're expressing normal
           | Typescript types, you have to use entirely different syntax.
           | It's good that you can usually avoid double-definition, but
           | it's still a big barrier that shouldn't be necessary.
        
           | tommy_axle wrote:
           | There's also typescript-to-zod that makes it possible to
           | generate the zod schemas from your types.
        
         | MrBazlow wrote:
         | A lot of the focus by the TypeScript team is focused on
         | alignment with the JavaScript language these days and novel new
         | features such as run time types have all but been dismissed or
         | at the very least pushed behind the TC39 JavaScript types
         | proposal. Much like using decorators on variables outside of
         | class structures was.
         | 
         | Having said that, TypeScript allows plugins, these are very
         | rarely used as they augment the language by introducing other
         | features that are transformed into the resulting JavaScript
         | files. One plugin that relates to your suggestion of run time
         | types is called Typia, it permits you to use your TypeScript
         | type signatures at runtime with guards like
         | `assert<MyType>(myValue)` where it intercepts the function call
         | to construct an exhaustive if statement in the transpiled
         | JavaScript checking the nature of the passed variable.
         | 
         | So while I don't see it being a part of the language in the
         | next four to six years, there are at least libraries out there
         | already that allow you to do it today.
        
         | hajile wrote:
         | If JS ever adds type checking, I hope it doesn't choose
         | Typescript.
         | 
         | We need a type system that is actually sound and TS is
         | intentionally unsound. We need a type system that doesn't allow
         | bad coding practices like TS does. We need a type system that
         | enforces program design that allows programs to be fast. We
         | need a Hindley Milner type system.
         | 
         | If you want a module to be typed, add a `"use type"`. This
         | should disallow bad parts of the language like type coercion.
         | It should disallow things that hurt performance like changing
         | object shape/value type or making arrays of random collections
         | of stuff. Incoming data from untyped modules would either
         | coerce or throw errors if coercion can't be done at which point
         | the compiler can deeply-optimize the typed code because it
         | would have far stronger type guarantees and wouldn't have a
         | risk of bailing out.
        
           | ahuth wrote:
           | What bad coding practices does TS allow, and why are they
           | bad?
        
             | hajile wrote:
             | If there's a bad way to write JS, TS has something
             | available to make sure it's typed.
             | 
             | Does TS help you keep your functions monomorphic so they'll
             | get optimized by the JIT? nope
             | 
             | Does TS keep your object shape from changing so it will get
             | optimized by the JIT? it actively does the opposite giving
             | TONS of tools that allow you to add, remove, modify, and
             | otherwise mess up your objects and guarantee your code will
             | never optimize beyond the basic bytecode (making it one or
             | two orders of magnitude more slow than it could otherwise
             | be).
             | 
             | TS doesn't do anything to prevent or even discourage these
             | kinds of bad decisions. They "type soup" many projects fall
             | into is another symptom of this. The big reason the types
             | become such a mess is because the underlying design is a
             | mess. Instead of telling programmers "fix your mess", TS
             | just releases even more features so you can type the
             | terrible code without fixing it.
        
               | tln wrote:
               | > Does TS keep your object shape from changing so it will
               | get optimized by the JIT? it actively does the opposite
               | giving TONS of tools that allow you to add, remove,
               | modify, and otherwise mess up your objects and guarantee
               | your code will never optimize beyond the basic bytecode
               | (making it one or two orders of magnitude more slow than
               | it could otherwise be).
               | 
               | Can you elaborate or point to some of the tools? So I
               | know what tools I may need to avoid
        
               | hajile wrote:
               | JS JITs use something called an inline cache (IC) to
               | speed up the lookup of object shapes. JS JITs consider it
               | to be a different shape if the keys are different (even
               | if just one is added or removed), if the values of the
               | same key are different types, and if the order of the
               | keys change.
               | 
               | If you have a monomorphic function (1 type), the IC is
               | very fast. If you have a polymorphic function (2-4
               | types), the IC function gets quite a bit slower. They
               | call 5+ types megamorphic and it basically foregoes IC
               | altogether and also disables most optimizations.
               | 
               | TS knows how many variants exist for a specific function
               | and even knows how many of those variants are used. It
               | should warn you when your functions are megamorphic, but
               | that would instantly kill 90% of their type features
               | because those features are actively BAD in JS.
               | 
               | Let's illustrate this.                   interface Foo {
               | bar: string | string[]           baz?: number
               | blah?: boolean         }
               | 
               | Looks reasonably typical, but when we use it:
               | function useFoo(foo: Foo) { .... }
               | useFoo({bar: "abc", baz: 123, blah: true}) //monomorphic
               | useFoo({bar: "abc", baz: 123})             //now a slower
               | polymorphic         useFoo({bar: "abc"})
               | useFoo({bar: ["b"], baz: 123})          useFoo({bar:
               | ["b"], baz: 123, blah: true}) //we just fell off the
               | performance cliff
               | 
               | As you can see, getting bad performance is shockingly
               | easy and if these calls were across five different files,
               | they look similar enough that you'd have a hard time
               | realizing things were slow.
               | 
               | Union/intersection aren't directly evil. Unions of a
               | single type (eg, a union of strings) is actually great as
               | it offers more specificity while not increasing function
               | complexity. Even if they are a union of different
               | primitive types, that is sometimes necessary and the cost
               | you are paying is visible (though most JS devs are
               | oblivious to the cost).
               | 
               | Optionals are somewhat more evil because they somewhat
               | hide the price you are paying.
               | 
               | [key:string] is potentially evil. If you are using it as
               | a kind of `any`, then it is probably evil, but if you are
               | using it to indicate a map of strings to a type, then
               | it's perfectly fine.
               | 
               | keyof is great for narrowing the possible until you start
               | passing those keys around the type system.
               | 
               | Template unions are also great for pumping out a giant
               | string enum (though there is a definite people issue of
               | making sure you're only allowing what you want to allow),
               | but if they get passed around the type system for use,
               | they are probably evil.
               | 
               | Interface merging is evil. It allows your interface to
               | spread across multiple places making it hard to follow
               | and even harder to decide if it will make your code slow.
               | 
               | Overloads are evil. They pretend you have two different
               | functions, but then just union everything together.
               | 
               | Conditional types are evil. They only exist for creating
               | even more complex types and those types are basically
               | guaranteed to be both impossible to fully understand and
               | allow very slow code.
               | 
               | Mapped types are evil. As with conditional types, they
               | exist to make complex an incomprehensible types that
               | allow slow code.
               | 
               | Generics are the mother of all that is evil in TS. When
               | you use a generic, you are allowing basically anything to
               | be inserted which means your type is instantly
               | megamorphic. If a piece of code uses generics, you should
               | simply assume it is as slow as possible.
               | 
               | As an aside, overloads were a missed opportunity. In
               | theory, TS could speed everything up by dynamically
               | generating all those different function variants at
               | compile time. In practice, the widespread use of generic
               | everything means your 5mb of code would instantly bloat
               | into 5gb of code. Overloads would be a great syntax to
               | specify that you care enough about the performance of
               | that specific function that you want to make multiple
               | versions and link to the right one at compile time.
               | Libraries like React that make most of their user-facing
               | functions megamorphic could probably see a decent
               | performance boost from this in projects that used TS
               | (they already try to do this manually by using the
               | megamorphic function to dispatch to a bunch of
               | monomorphic functions).
        
             | DexesTTP wrote:
             | TS allows you to pass a read-only object to a method taking
             | a read-write value:                   type A = { value:
             | number; }         function test(a: A) { a.value = 3; }
             | function main() {           const a: Readonly<A> = { value:
             | 1 };           // a.value = 2; <= this errors out
             | test(a); // this doesn't error out
             | console.log(a); // shows 3         }
        
           | iimblack wrote:
           | Rescript?
        
       | jvanveen wrote:
       | I just switched to Bun for typescript support, a free bundler and
       | better performance. Iojs flashback all over :)
        
         | XCSme wrote:
         | Does Bun always work for you? For me, none of my projects
         | worked to run "bun install" on.
        
       | DrMiaow wrote:
       | Without some kind of transformation on `enum` isn't this mostly
       | useless? `enum` is heavily used in many TypeScript code-bases.
        
       | cryptica wrote:
       | It's interesting how TypeScript beat Flow in terms of popularity,
       | and yet everyone is now calling for TypeScript to be more like
       | Flow (to focus on plain type checking instead of transpilation;
       | just strip out the type annotations)... And most of those people
       | don't even know about the existence of Flow.
       | 
       | The sad thing about the tech sector is that you can be right
       | about something and yet still lose the hype-wagon popularity
       | contest. Then your competitor copies your original idea... The
       | exact same idea which they had previously claimed was inferior.
       | 
       | It seems that the idea was inferior purely on the basis that it
       | wasn't their idea. As soon as they've appropriated the idea,
       | suddenly it's the best idea in the world.
        
       | zaphod420 wrote:
       | I would rather raw dog JavaScript than write Typescript.
       | Typescript is an abomination.
        
         | halfmatthalfcat wrote:
         | Thank god you're in the minority with that opinion
        
       | nthngy wrote:
       | IMAO writing (hard-coding) TypeScript is deprecated and a waste
       | of time. With all tech available nowadays it is possible to do
       | the entire type check automatically in the IDE, even more so now
       | with the help of AI. It's just a matter of time when we stop
       | hard-coding type info. Better invest time and money in getting
       | the IDE's work better for us.
        
       | zelphirkalt wrote:
       | If this means, that one day I don't need to use a bundler any
       | longer to make a website using TypeScript, I am all for it.
        
       | umvi wrote:
       | Side note, but IMO Typescript is too complicated. They should
       | have stuck to a reasonably simple type system but now I see
       | projects with incomprehensible and frankly unmaintainable
       | typescript consisting of extremely complex generics, type
       | conditionals, and type constraints. Basically if you aren't
       | careful you'll find your project metaprogramming in typescript's
       | turing complete meta language...
        
         | ChicagoBoy11 wrote:
         | This is something I've struggled with as a mostly solo dev.
         | I've most often just stuck with vanilla javascript because of
         | course that's good enough, but definitely there have been times
         | where I hoped I had some typing helping me out. Alas, I haven't
         | quite finagled the art of finding a way to use it "just a
         | little bit."
        
         | andrewmcwatters wrote:
         | TypeScript in its current usage reminds me of Hello, World! or
         | FizzBuzz Enterprise Edition. There's almost more code dedicated
         | to typing than the actual running software itself in some
         | codebases I've seen.
         | 
         | The authors trick you with reasonable examples on
         | https://www.typescriptlang.org, but in the wild, you have these
         | ridiculous codebases that couldn't control themselves and they
         | have this insane ratio of multiple declaration files to actual
         | source files and you have to ask yourself, "Are you writing
         | software to get something actually done, or do you just like
         | write type definitions?"
         | 
         | Even people who write in C++ don't go to the lengths that
         | TypeScript users do. It's super weird and cult-like.
        
           | umvi wrote:
           | To be clear, I do like the type-checking benefits of
           | TypeScript, but it requires some discipline to keep it
           | simple. Get one unchecked TS astronaut on the team and the
           | TypeScript can get complex and esoteric very quickly.
        
           | sureIy wrote:
           | I also get lost in types sometimes, but the point of types is
           | that they help you. Typescript lets you just use `as any` and
           | `as unknown` as you please, but you want complex constraints
           | you will need complex types.
           | 
           | There are some type libraries that parse GraphQL queries and
           | CSS selectors. They're crazy to look at but they're hugely
           | helpful.
        
             | umvi wrote:
             | Maybe I just have bad luck, but most of the libraries I've
             | tried that are "crazy to look at" seem good in theory but
             | are janky in practice. For example, openapi-fetch
             | (https://github.com/openapi-ts/openapi-
             | typescript/tree/main/p...), on paper seems great, but has
             | lots of jank in practice.
             | 
             | And I would wager the bugs and jank are in no small part
             | due to the extremely complex generics/constraints.
        
       | jdeaton wrote:
       | Isn't the whole idea of TS that you just convert to JS to run it
        
         | WorldMaker wrote:
         | Yes. The question is where you do the conversion and how much
         | of a conversion to do. This allows a key conversion (type
         | stripping) directly at load time by Node rather than needing an
         | extra step (an external type stripper such as Typescript or
         | esbuild) sometime before passing the file to node for loading.
        
       | 65n56nm5665m56 wrote:
       | I beg of thee, do not do this. I get that people love typescript
       | but I am already running into a problem where javascript
       | resources are written in typescript by default with nothing for
       | regular javascript. This is the same problem that happened when
       | JQuery hit its peak popularity and an overwhelming amount of
       | resources and guides amounted to "Oh just do this in JQuery"
        
         | lolrsten349 wrote:
         | Tell me you're out of touch without telling me that you're out
         | of touch.
         | 
         | jQuery was so popular because writing anymore than a few lines
         | of vanilla JavaScript was an *awful* experience due to all
         | differences in browsers.
         | 
         | When things eventually standardized-ish and jQuery became
         | unnecessary, other libraries/ecosystems popped up (e.g.
         | React/JSX) to make writing webapps easier because writing
         | anymore than a few lines of vanilla JavaScript was still an
         | *awful* experience.
         | 
         | When webapps grew in size and scope, other "transpiled"
         | languages popped up (e.g. TypeScript) because writing anymore
         | than a few lines of vanilla JavaScript is *still an awful*
         | experience.
         | 
         | We're stuck with JavaScript due to past decisions, but let's
         | not pretend it's actually a good tool. If it were we wouldn't
         | need 50,000 tools/frameworks/transpiled languages to hide how
         | terrible it is.
        
           | sureIy wrote:
           | JavaScript is not terrible and I don't understand where you
           | got that from. Since ES2015 came out, it's actually rather
           | pleasant.
        
         | pansa2 wrote:
         | > _javascript resources are written in typescript by default
         | with nothing for regular javascript. This is the same problem
         | that happened when JQuery hit its peak popularity_
         | 
         | That's definitely a potential issue - JavaScript is the
         | fundamental standard, not JQuery and not TypeScript. Certainly
         | there are situations where maximum forward-compatibility is
         | important (learning resources are a good example) and for
         | those, vanilla JavaScript is the best choice.
         | 
         | All of the old resources that relied on JQuery are now
         | hopelessly outdated, whereas the contemporary ones that used
         | plain JavaScript are as valid now as when they were written.
         | I'm sure the same will be true of TypeScript vs JavaScript when
         | the next big thing comes along.
        
           | silverwind wrote:
           | > the contemporary ones that used plain JavaScript are as
           | valid now as when they were written.
           | 
           | True, but on the other hand, almost any JS code snippet
           | written 20 years ago has better and more elegant alternatives
           | today. APIs evolve all the time.
        
       | tracker1 wrote:
       | Nice to see this, and important to stay closer to parity with
       | Deno and Bun.
        
       | torginus wrote:
       | I might be ignorant but wasn't there a plan to add Typescript
       | support to the browser itself?
       | 
       | In which case wouldn't V8 support TS directly without needing to
       | transpile?
        
         | herpdyderp wrote:
         | Yes. That is noted in the PR:
         | 
         | > There is a TC39 proposal for type annotations
         | 
         | Which links to https://github.com/tc39/proposal-type-
         | annotations
         | 
         | It is a long ways off though.
        
         | jokoon wrote:
         | all browsers would have to agree, the language would have to be
         | very well defined and well supported across all those browsers.
         | 
         | that would be a lot of work
         | 
         | I would rather see new WASM features instead
        
       | unilynx wrote:
       | If this feature ever becomes the default (ie not behind a flag) -
       | how will the NPM ecosystem respond? Will contributors still
       | bother to build CJS end EJS versions when publishing a NPM
       | module, or just slap an 'engine: nodejs >= 25' on the
       | package.json and stop bothering with the build step before
       | pushing to NPM ?
       | 
       | I _personally_ would very much prefer if NPM modules that have
       | their original code in TS and are currently transpiling would
       | stop shipping dist / _.cjs so I unambiguously know where to put
       | my debugger /console.log statements. And it would probably be
       | very tempting to NPM contributors to not have to bother with a
       | build step anymore.
       | 
       | But won't this start a ripple effect through NPM where everyone
       | will start to assume very quickly 'everyone accepts TS files' -
       | it only takes one of your dependencies for this effect to ripple
       | through? It seems to me that nodejs can't move this outside an
       | opt-in-experimental-flag without the whole community implicitly
       | expecting all consumers to accept TS files before you know it.
       | And if they do, it will be just months before Firefox and Safari
       | will be force to accept it too, so all JS compilers will have to
       | discard TS type annotations
       | 
       | Which I would personally be happy with - we're building
       | transcompiling steps into NPM modules that convert the ts code
       | into js and d.ts just to support some hypothetical JS user even
       | though we're using TS on the including side. But if node accepts
       | _.ts files we could just remove those transpiling steps without
       | ever noticing it... so what's stopping NPM publishers from
       | publishing js/d.ts files without noticing they broke anything?
        
         | nfriedly wrote:
         | For the old libraries I maintain that are typescript and
         | transpiled into .cjs and .mjs for npm, I'll probably just start
         | shipping all three versions.
         | 
         | For a new thing I was writing from scratch, yeah, I might just
         | ship typescript and not bother transpiling.
         | 
         | [edit: Apparently not. TS is only for top-level things, not
         | libraries in node_modules according to the sibling comment from
         | satanacchio who I believe is the author of the PR that added TS
         | support and a member of the Node.js Technical Steering
         | Committee]
        
           | WorldMaker wrote:
           | Why are you still transpiling to .cjs in 2024? ESM is
           | supported in every LTS version of Node now. We can kill CJS,
           | we have the power.
        
             | nfriedly wrote:
             | Because I don't like breaking things unnecessarily. Some of
             | my libraries are 10 years old and depended upon by
             | similarly old projects that are not using ESM and probably
             | never will.
             | 
             | Besides, it's already going through one transpilation step
             | to go from TS to ESM, so adding a second one for CJS really
             | isn't that much hassle.
             | 
             | I think if node.js had made require() work with ESM, I
             | could probably drop CJS. But since that's probably never
             | going to happen, I'm just going to continue shipping both
             | versions for old projects and not worry about it.
        
               | sureIy wrote:
               | > adding a second one for CJS
               | 
               | Nobody is arguing for that. Once you ship ESM, you can
               | continue shipping ESM.
               | 
               | In Node 22 you can even require() ES modules (with an
               | experimental flag, at the moment)
        
               | nfriedly wrote:
               | > > _adding a second one for CJS_
               | 
               | > _Nobody is arguing for that. Once you ship ESM, you can
               | continue shipping ESM._
               | 
               | I'm not sure I follow you there. I did continue shipping
               | ESM.
               | 
               | > _In Node 22 you can even require() ES modules (with an
               | experimental flag, at the moment)_
               | 
               | Oh, I didn't know about that, cool! Once it becomes un-
               | flagged I might consider dropping CJS.
        
               | WorldMaker wrote:
               | > I think if node.js had made require() work with ESM, I
               | could probably drop CJS
               | 
               | Why is making downstream have to switch to `await
               | import()` that big of a deal?
               | 
               | You can use async/await in CJS just fine. Sure, sometimes
               | you may need to resort to some ugly async IIFE wrappers
               | because CJS doesn't support top-level await like ESM
               | does, but is that really such a big deal?
               | 
               | Sure, it's a breaking change, but that's what semver
               | major bumps are for.
               | 
               | I just think that if projects want to stay in CJS they
               | should learn how to use async/await. I clearly don't
               | understand why CJS libraries feel a need synchronous
               | require() for everything. (Though to be fair, _I 've_
               | also never intentionally written anything directly in
               | CJS. I learned enough in the AMD days to avoid CJS like a
               | plague.)
        
               | nfriedly wrote:
               | > _Why is making downstream have to switch to `await
               | import()` that big of a deal?_
               | 
               | > _You can use async /await in CJS just fine. Sure,
               | sometimes you may need to resort to some ugly async IIFE
               | wrappers because CJS doesn't support top-level await like
               | ESM does, but is that really such a big deal?_
               | 
               | It might seem like a small amount of work, but for a
               | library one must to multiply that small amount of work by
               | the number of users who will have to repeat it. It can be
               | a quite large amount in aggregate. And, for what benefit?
               | So I can drop one line from my CI config? It just seems
               | like a huge waste of everyone's time.
               | 
               | Also, as a library user, I would (and occasionally do)
               | get annoyed by seemingly unnecessary work foisted on my
               | by a library author. It makes me consider whether or not
               | I want to actually depend on that library, and sometimes
               | the answer is no.
        
               | WorldMaker wrote:
               | > multiply that small amount of work by the number of
               | users who will have to repeat it
               | 
               | This is probably where we have the biggest difference in
               | our calculations. I know there's a lot of pain in legacy
               | CJS systems, but from my view (which is maybe more
               | "browser-oriented", which is maybe a bit more Deno/Bun-
               | influences, which comes from a "Typescript-first"
               | mentality going way back to 0.x) it is more legacy "giant
               | balls of mud" maintained by a sparse few developers. I
               | don't see this multiplicand as very big on the scale of
               | library user count. Most CJS for years and years has been
               | transpiled from Typescript or Rollup; most CJS only
               | exists to be eaten by Webpack or other bundler, many of
               | which today rewrite CJS to ESM anyway. From what I see a
               | lot of CJS seems either transpiled out of habit (for some
               | notion of supporting Node < 10 that doesn't make sense
               | with current security support) or by accident (by a
               | misconfigured tsconfig.json, for example, and then often
               | looping back through a transpiler again back to ESM). The
               | way we cut through the Gordian knot of we're all doing
               | too much transpilation to/from CJS is to start
               | eliminating automated transpilation to CJS in the first
               | place. Which is why I find it useful every time to ask
               | people what they are really trying to do when transpiling
               | to .cjs today.
               | 
               | Of course, if your multiplicand is lines-of-code
               | impacted, because I agree there are some great big huge
               | piles of mud in CJS that are likely stuck that way for
               | lack of developers/maintainers and lack of
               | time/budget/money, then worrying about the minority of
               | users still intentionally using CJS is worth caring
               | about, and my sympathies in that situation.
               | 
               | You, of course, know your library's users better than me
               | and maybe you do have a lot of CJS users that I just
               | wouldn't consider in my calculations. I'm not going to
               | stop you from transpiling to CJS if you find that
               | necessary for your library. That's your judgment call. I
               | just wanted to also make sure to ask the questions of "do
               | you really need to?" and "how many users do you actually
               | think it will impact?" out loud. Thanks a lot for the
               | conversation on it, and I'm still going to be a radical
               | banging the "CJS Must Die" drum, but I understand
               | pragmatism and maintenance needs, especially those of
               | legacy applications, and mostly just want to make sure
               | the conversation is an active one and a lot less of
               | passively transpiling stuff that doesn't really need it.
        
             | thr0w wrote:
             | > ESM is supported in every LTS version of Node now. We can
             | kill CJS, we have the power.
             | 
             | I'd rather kill ESM. And it's not fully supported in Node.
             | It doesn't work in the REPL.
        
               | crabmusket wrote:
               | You can have a chat to all major browser vendors about
               | killing ESM :)
        
         | satanacchio wrote:
         | We dont support running .ts files in node_modules, this is one
         | of the main constraints to avoid breaking the ecosystem
        
         | Omerd6 wrote:
         | The legendary Ryan dahl is actually working on solving the
         | exact problem you described by creating a new package registry
         | called JSR.
         | 
         | Essentially what it does is allow you to upload your typescript
         | code without a build step so when other devs install it they
         | can see the source code of the module in it's original
         | typescript instead of transpiled JavaScript.
        
           | sam_perez wrote:
           | That's really cool. One of the benefits of the JS ecosystem
           | is the ability to step through code and crack open your
           | dependencies. Not sure if this would directly make this
           | possible when running your projects/tests, but it at least
           | sounds like a step in that direction.
        
           | meowtimemania wrote:
           | it must install compiled and uncompiled versions? Otherwise
           | node (without the above flag) would throw errors when it
           | encounters types in node_modules
        
       | winrid wrote:
       | anyone know, for example where this is already done with Bun, how
       | this impacts startup times with large applications?
        
       | brundolf wrote:
       | I feel like Deno and Bun have lit a fire under the Node team to
       | finally modernize things people have been desperately wanting for
       | years. Great to see!
        
       | RadixDLT wrote:
       | Oh, great, people love JavaScript. What a shock.
        
       | olalonde wrote:
       | It just took 3 weeks to merge this? Seems really fast by Node.js
       | standards. I assume it was discussed before the PR was opened?
        
       | dangoodmanUT wrote:
       | NodeJS is the ChatGPT of JS.
       | 
       | Eventuall they add the feature something else has, and then
       | everyone uses it again instead of the other thing.
        
       | low_tech_punk wrote:
       | Is there a slippery slope? Node -> Browser
        
       ___________________________________________________________________
       (page generated 2024-07-25 23:05 UTC)