This cones as no surprise to me, as TypeScript is a transpiled language. I know this is probably an unpopular opinion at HN, but I am a huge supporter of plain old JavaScript and have never really seen the benefits of DSLs like this. Coffeescript was especially pointless to me when I had to use it on a project. My reasons are simple: debugging becomes much more difficult when you add a layer of abstraction. It compiles to JavaScript anyway, and sometimes it does so in very odd ways that makes it difficult to understand the relationship between what you wrote and what it produced. IMO, straight JavaScript is more than adequate for most scenarios if you know the language well enough, especially with the powerful features built into the more recent versions. In my 20 years as a (mostly) front-end developer, I have not heard any convincing argument in favor of a transpiled JavaScript pseudo-language. Of course there are advantages, but most of these can be solved with better code organization and architecture.
I will say I don’t quite feel as strongly about CSS pre-processors like SCSS, which I really enjoy, however I still prefer plain old CSS for the same basic reasons.
I think there is a way to get all of the "good parts" of Typescript, mainly type checking, without introducing the bad, mainly transpiling. I recently started just running Typescript on Javascript files, where all of the types are specified via JSDocs. It was a refreshing experience, and I highly recommend. The Typescript website[1] has pretty good documentation for it.
Came here to upvote typescript with jsdocs too. We use it in our project and it’s been really helpful. No overhead and you get the nice dev experience of typed code. Been doing it for 2 years, have yet to encounter a situation that would be solved by using ts compilation.
My team started development of a React SPA. It was initially written with jsx. As we're starting to implement more, I'm finding more and more cases where the js code was wrong; property names that don't exist, wrong types being passed around, and non-existent props being used.
How do you suggest addressing this in a 10 dev team when developing in js?
You should absolutely use TypeScript for this. This is exactly what TS is for, to assert your types (proptypes, interfaces, classes, etc.) Switch to .tsx files too. There's a bit of a learning curve for TS, but it's well worth it. You should also type your global store (whether it's in react or redux), your dispatchers, and your action creators. And if you're doing redux, consider redux-toolkit. Turn off implicit any, assert types on everything you can, don't use !, learn about union types.
Hit me up in the e-mail in my profile if you want to discuss this further, would be happy to help and discuss my reasoning further. I've been doing a LOT of TS code recently on all the major target platforms for React - browser, electron, and react-native. I manage a team who's built several applications now and we use TS for everything, including an automatically-generated TS api interface that exposes types from our C# REST backend using swagger directly to the client code.
As someone who's recently jumped into a TS codebase after using just JS for years, a blog post or resource with these tips would be very nice (even though some are obvious, a lot of people don't know they exist. Disabling implicit any was a PITA/huge help for me.) Do you say don't use ! because you can't make just anything truthy in TS, or is there another reason?
Check out https://reasonml.org - created by Jordan Walke, the creator of React. Reason offers the best of both worlds - type safety without getting in the way and faster JS than what you'd write by hand.
As much as I would shill reasonml. Think before you adopt - it still requires more upfront work than typescript (you will have to write bindings for most things even popular stuff. You might end up fighting it too.) but as parent said, you get more expressiveness (algebraic types, powerful pattern matching, immutability, partial application etc) and sound type system with a speedup on both transpile times and actual run time.
You can leverage ocaml/ml as well as js ecosystem. Mix different files and syntax.
To add to this, there are at least 3-4 pain points which... are just a pain with ReasonML, that can kinda counteract its type system.
- non-standard ordering of arguments between belt/standard library
- Ocaml's standard library actually generally avoiding the Option/Result type, in preference of exceptions, which is unexpected and a pain since it's an ML.
- package management involves manually adding things to the bsconfig (has this changed?)
- things randomly break between relatively minor Bucklescript versions, they broke something pretty important in like a .x release when I was messing around with it
- server side isn't good. It technically works but all the bindings are old or terribly documented, and you never really know if it's not going to blow up at some point.
Otherwise, I actually quite like it! None of those are actual core language complaints.
Slightly off topic but has anyone tried Hegel? https://github.com/JSMonk/hegel, looks like a nice mix of reason,ts and flow. It's just Js with types + type inference.
These issues seem to be a symptom of bad/inexperienced developers rather than the tooling. Proptypes and linting may also help with some of your type/prop issues but competency will trump tooling most times.
You would end up defining PropTypes, and ESLint is capable of keeping you in check there.
It's much worse than just using TypeScript (only at runtime, PropTypes aren't that useful anywhere else, PropType syntax doesn't match Flow, TS, or jsdoc, ESLint can't check any PropTypes you spread in), but it can get you by in a pinch.
I think most of this can be solved by proptypes, although true proptypes is not as thorough as TypeScript.
I had some negative experiences with typescript in a large React project but in that case the most negative experience was that often the type definitions provided by React and common type libraries didn't match our needs, which made doing something that would normally be quick difficult and long.
The reason for types not matching was often that we needed to generate HTML emails as part of things, which means you need a lot of deprecated attributes, so probably you won't have this problem.
You need rigorous tests though. At some point you end up with a hacked on version of typing. I appreciate that Typescript will tell me "this value might be null, and that function doesn't handle null" rather than writing a bunch of runtime checks to make sure the value isn't something invalid, and then writing tests to make sure those work.
You need rigorous tests anyway. Typescript is checking types only at compile time if I'm not mistaken and what it detects is only a set of problems. Yes it's nice that you can detect some types errors thanks to typescript, but is the development overhead worth it? With eslint, sonarqube, and tests, I think typescript is not that useful and annoying to use.
For example I contributed to Typescript's definitely typed project in the past. To make typescript more useful. But I ended up spending so much time writing type definitions. After all, I rather have some NaN or "undefined is not a function" exceptions during development.
You need less tests in a type safe language. Especially in a good one like reason / scala.js / elm. Typescript is just not very safe, its type system is unsound by design because compatibility with JS is their #1 priority.
Typescript helps you to avoid most obvious bugs(wrong classes, non-existent properties, basically to escape the undefined hell) that is the point of it, which I really like and find enormously helpful for medium-size JS project (10k-50k LoC)
Also I don't think the transpiler argument holds in today's JS ecosystem. Everything is transpiled. Unless you are developing in barebone ES5 syntax and avoid babel as a whole, then some level of transpliation is inevitable. Yet, I didn't find debugging that much difficult with correct setup.
If you target browsers that are installed by default on operating systems that are still receiving security updates, you have to support Windows 8.1 and thus IE 11 for another two and a half years, alas.
One of the best things about TypeScript is that it compiles to very normal-looking JS. Its compilation step is almost entirely just stripping out type data, by design. I went through coffeescript pain before and like many didn’t expect to ever be happy to use a compiles-to-JS language, but TS really is different. If they change direction and start to add tons of stuff that doesn’t translate cleanly, I’ll get worried. Until then it’s very nice and comes with an escape hatch of just taking its output and making that your new codebase. It’s that clean-looking.
I think if you call it a DSL and are comparing it to CoffeeScript, you might be misunderstanding what TypeScript is/does for you, and you might be missing out.
If you're using ESLint, I'm quite sure you'd like TS as well, so if that is the case, you might want to give it an actual chance.
If your comment were code, TypeScript would have caught your typo at compile time, versus JavaScript where your users would have experienced this (potentially catastrophic) error at runtime.
Had the original typo been corrected, TS would have also caught your reply and told you to update it.
This is the main value we get out of TS. If we rename a property on a viewmodel, we then update a TS file containing all the models. In this trivial example an auto refactor might propagate the change, but if it didn’t we get type errors all over the application telling us to change this. In JS, there’s an overwhelming possibility we miss one of these, and it isn’t picked up until production.
Worse, it might even work properly in production for many common use cases, then blow up in your face somewhere down the line.
Real-life example: I recently came across some code that checked for a rare error. It was in the form,
if (object.property === CONST_ERR_CODE) { /* handle it */ }
At some point, `object` had been refactored and `property` was no longer on it, effectively turning the statement into "if (false)".
This class of issue is probably my least favorite thing about js at any type of scale. It's so incredibly permissive that even simple tweaks need to be scrutinized carefully, whether by human eyes or unit tests. Using human eyes means I can't write js when I'm tired at the end of the day (otherwise the perfect time for small, no-functional-changes refactoring), and unit tests for trite details are boring -- I'd rather spend that effort up front, to appease the compiler.
On the other hand, js is incredibly nice for prototyping, before I have to care about edge cases.
Amen. I don't transpile to JS anymore. If the client is IE (no updates for 7 years?) and doesn't feel like installing FF, Chrome, Edge, or whatever, then it is what it is.
Modern static ESModule JS is quite good. I have several projects north of 30KSLOC written in modern JS. I'm not living in "undefined hell" because I use named-export ESModules, I check types all over, and I write quality tests. A little discipline goes a long way.
Modules are my favorite part of js (and ts, mostly). One file = one module with all imports/exports explicit is so incredibly right. `git grep`ing to figure out which other file a random implicit import came from is a real PITA.
That's true. But with TS I have to declare types, import typings, maintain a build process to run the TS compiler, and so on. Moreover, static typing comes with added tediousness, and I personally feel that it's not worth the freight.
I feel the exact same. Reminds me too of Nassim Taleb's idea that, if something as already existed X years, it's likely to exist another X years. I'm skeptical of the staying power of these transpilers.
TypeScript has been around since 2012, and it has since won in the marketplace of ideas, becoming the single most popular language to transpile to ES# and beating a well-resourced competitor in Flow.
The type war was "won" by TypeScript, and I expect it's just a matter of time before types make it into the standard. The benefit of winning so completely and having such enormous popularity is that its ideas are very likely to make it into the standard such that no transpilation will be necessary.
> just a matter of time before types make it into the standard
I hope so too. TypeScript has done so many things right in its design and implementation - starting from Anders Hejlsberg, with expertise in creating numerous languages; backward compatibility to allow gradual and seamless migration from JS to TS; structural typing; editor/IDE integration via language server; good documentation; corporate backing (maybe not necessary, but like React, I think it was a big factor in its wide adoption).
This is valid when you write java(scripts) a code base that don't expend to multiple files and become a whole Application like we have today in the front end landscape.
You solve scripting language problem with better code organization? While in the first place the language was designed to solve scripting problems, DOM manipulations, now you can use JavaScript to build backends and SPA's hybrid apps, and most importantly some huge code base of libraries like Gatsby, vscode, where large teams are collaborating in the same project. How would you solve all the runtime errors? How would you solve expending the capability of your code editor? How would you solve refactoring? Just to name very few of what something like Typescript is capable of.
Do you use Babel to polyfill JS? Minify? Concatenate? You’re transpiling. And not much more than TS. There is very little logic change that TS does and most of it is essentially the same as what Babel would do for polyfill reasons.
I'm not OP, but in my case, no. I don't. I write a roughly ES7, and if you're on an ancient phone/PC, oh well. I really don't care. Not because people using those devices don't matter, but because I am writing code for a company in which I have a say in what hardware/software is provided to employees. I don't have to support IE. That's true of a lot of developers, for whom Babel is a waste of time.
The reason those transpilers exist is that the target language is so excruciatingly awful. At least to those willing to endure the pain of transpiling.
It's an unhappy situation for all involved really. JS should be a language that targets some kind of bytecode that the browser executes rather than being a direct target.
Perhaps WASM will some day replace all webpage scripting allowing everyone to use languages of their choice.
Non platform languages introduce those extra layers, while bringing along their own FFI issues, idiomatic libraries and other set of issues to care about.
I only use TypeScript alongside Angular, as one could somehow consider Angular to be the platform, for anything else Web related, pure JavaScript with script tags (yes I don't bother with JavaScript transpilers either).
At this point, I don't believe it would be unrealistic for MSFT to make TS to get its own engine or a fork of V8 similar to how PHP became HACK over time for FB.
The problem with this argument is you're already compiling your JavaScript to JavaScript anyway. You already can't paste ES6 into the JS console. And don't even start if you're using JSX. I think the opposite: nobody should write JavaScript. You should write in any other language than JavaScript, there are hundreds to choose from. https://github.com/jashkenas/coffeescript/wiki/List-of-langu...
The problem with your argument here is that you're assuming that the person you're replying to is using ES6 and/or JSX when they outright said they prefer just using "plain old JavaScript" which is neither of those things, so you're bypassing their argument fully.
Their point seem to be that no matter what language you prefer to be compiled to JS, in ends up being JS anyway so you might as well write JS directly, because of the reasons provided in the last post. I don't agree with them (ClojureScript is the language of choice for me), but you're not arguing with good faith here.
ES6 is plain old JavaScript. I think the parent commenter's point was that even when you're writing plain JS, if you target browsers (and old browsers specifically) or e.g. a large range of Node.js versions, you often still need to transpile it. This naturally doesn't apply if you target a specific runtime version (e.g. a specific Node.js version).
That being said, the commenter above them could've also been referring to old old JavaScript where no transpilation is needed to reach practically every target environment.
ES6 implies transpiling, or polyfilling, IF you want to support most browsers still currently used.
It seemed to me that the author was describing the (somewhat common?) practice of writing client code directly in ES5 and perhaps polyfilling any missing features for any targeted browsers that required specific fills.
I, personally, find ES6 to be ugly and requires me to pretend all sorts of things that are not true for the targeted runtime.
It's like a whole fake world, so I'll prefer to avoid it unless there's some obvious reason to use it, as in an existing front-end build toolchain and a spec to use ES6, etc.
Greenfield? I guess Svelte and such will use it, but if Typescripting, then one will just write Typescript, right?
Hmmm, I have more than one current project in pure ES5, as terrible as it is. I have one polyfill file with stuff like Object.keys and things that organically accumulated over time, and should probably be cleaned of obsolete nonsense but it's 6k LOC, and otherwise I need to remind myself to use my XHR abstraction, as I automatically still type stuff like "if xhr.readyState == 4 && xhr.status = 200" like a doofus... such is life in wart-land.
I will be happy when I leave wart-land, but only when I really leave wart-land, not when it's just "lipstick on the wart"-land.
Types and classes sound nice, but only if they really exist, and not as mere compiler advice. A type is really a memory shape/size/structure in compiled languages.
Ok, having said all of this heretical nonsense...
(and yes, I've used React, Vue, etc. I tend to like Mithril best, and avoid JSX as I've no problem with hyperscript, and have even made my own lousy reactive hyperscript that I don't use (lol) in favor of Mithril)
... i DO have to say that Typescript seems like a nice/useful tool for teams, were transpiling to be accepted for the project needs, after weighing the costs/needs.
I am recently rather fascinated by Svelte, and I'm mostly trying to break things and see what generated code looks like, etc.
I'll admit that ES3 get's a bit useless, hence the polyfill.
Minified JS with single-letter variables is usually a hoot to read.
It's important not to read this as a critique of Typescript. Rather, it's a note that it's not a good fit for this one particular performance critical piece of code.
It sounds like they are discussing the central code runner of deno. I would have expected this to be compiled to JS in any case, but it seems like they are compiling the runner, then compiling user code. Of course that's slow. It's also not representative of a normal TS use case, which is unfortunate because I expect we'll see this discussion shared all over the web as an argument for dropping TS.
a) Any static type system has things that it can't express elegantly or maybe at all. In my experience, the more "meta" your project is, the more you're going to run up against these bounds. So it makes sense that this could be the wrong use-case for TypeScript.
b) There is a valid, broader point to be made here that while TypeScript itself doesn't carry any runtime overhead (by design), it can in some cases force you to contort your code, so that it can be type-verified, in ways that have a runtime impact. In my experience (a couple of years writing TypeScript professionally) this is uncommon and not a huge problem, but does happen occasionally. It's also worth noting that the vast majority of these cases can be papered-over using //@ts-ignore, "as" casting, etc. if necessary.
I don’t read that as a criticism of TypeScript at all. That is entirely self inflicted due to a name collision between an identity in their definition file and some weird class extension insanity.
I don’t use classes or inheritance in my own code and it’s incredibly liberating. The result is data structures and interfaces that are primitive and independent, which removes so much fragility.
In my entire experience as a programmer, I can't recall writing a prototype that was not eventually used as production code. If I wrote prototypes in JavaScript, I'd have to start all over again to rewrite them in TypeScript.
Meanwhile, people would be on my ass trying to understand why I can't just simply hook up that decent looking prototype to API and release it.
I started using Evan Wallace's TypeScript [0] implementation (and bundler) written in Go and it's pretty fast (there are benchmarks too). I'm surprised this kind of thing is not something Deno's pursuing. Having used esbuild I see the future of web tooling as not necessarily written in (or compiled to) JavaScript.
It's interesting, I wonder why the proposal doesn't talk about leaving TS code and simply ignoring the syntax using something like babel to preprocess it out (without needing to run the type checking outside of CI).
tsc can also do that, but I think there's something else here.
I'm not really sure what this post is getting at. I trust Ry knows the issue better, but from what I've read I have the same questions as everyone else here:
- Why is Deno defining interfaces and classes like that?
- Will this mean losing type checking in projects using deno?
- Why not strip types in development and only check at commit/push/build times?
FWIW Flow actually let you write type annotations as comments so that the code was syntactically valid JavaScript. I'm not sure if TS ever had something like this.
This is quite difficult to make sense of beyond the initial description so I’m not sure about the current status. But it would be a shame to lose valuable type info because compile times are long... isn’t there a tool out there that does nothing except strip types from TS files? If you used that you could get quick rebuilds when developing but retain type checking when you do a full build.
Hi, Sucrase author here. I'm also having a hard time understanding the rationale here, but it looks like it's maybe a nuance around self-hosting. In general, for any regular TS project, I'd certainly recommend decoupling typecheck and transpile as separate operations and running typecheck alongside lint. IMO one of the nicest things about TypeScript is that you can run your code before you've figured out how to get the types to check out.
They do consider swc (which has roughly the game goal as Sucrase) in the conversation, so it seems like there's some consideration of a transpile-only approach. TypeScript's built-in `transpileModule` is probably the most reliable and officially-supported way to get the equivalent, and is much faster than running TSC with typechecking.
Does this mean that their standard lib won’t have types, in the same way that Node’s doesn’t? I’m not entirely sure how it works but VSCode seems to have types for the Node standard library somehow and it’s really helpful. I assume that’s Microsoft’s work so does this basically mean that unless Microsoft do the same thing for Deno it’ll be a worse editing experience compared to Node in VSCode?
Or would the Typescript internals not have been available in that way anyway? It just seems hard to compete on ease of use with Node in VSCode without whatever magic is making the editor so smart - which I assume is something to do with Typescript.
No - you don't have to write the code in Typescript to get types - you can manually write type definitions for Javascript code.
In this case it would be even easier since it's already in Typescript and would presumably be a straight port, so all of those type definitions can be automatically generated from the existing code and will just work.
> ry So - to make a long story short - we're removing the types from internal code and making it pure JS
this reduces complexity and helps us ship a faster product. I acknowledge it's unfortunate to lose the type information, but it's really masking larger problems.
It's not going to happen immediately tho. We have a bit more work to figure out how exactly it should be done.
It's not going to be one big 9000 line file either.
But it might not be ES modules. depending on if we can make that work or not.
The “lose the type information” there suggested to me that they’re not planning to ship them at all.
I think that's in reference to losing the type information for their own development of that code. I'm almost certain they don't mean they will stop shipping type definitions for the public APIs.
This doesn't seem all that odd. I read this as a temporary solution to the fact that there's some real problems that TypeScript causes for the way their project is laid out and used with regard to certain types of introspection (noting duplicate classes) and performance (it's damn slow).
It's like them running the TypeScript compiler to generate one large JS file and using that intermediate as what people build against instead of the original TypeScript source. I'm not sure if this is what they're actually doing (or if they're somewhat manually doing the equivalent of it), but as a hopefully short-term workaround that allows them to solve the problems, that doesn't seem too bad (but it does possibly highlight some TypeScript problems).
Even if they actually move to a large core JS file that is the active development target, as long as they keep track of the TypeScript specifics (and don't code themselves into a corner assuming something works that they find much later errors), it may not necessarily be hard to go back to TypeScript from that (possibly with a lot of it automated with a lot of structured comments).
Part of what's slow is that they're type checking and compiling the code at the same time. Best practice for a project of this size would be to run type checking as a unit test and only transpile during the build. An incremental type check is also super fast, it's possible they don't have caching setup.
To me this reads more like a list of issues in the deno architecture, and how they integrated TypeScript, than any issue with TypeScript itself.
This makes me generally curious about Deno’s architecture/design. Anyone known much about it? Would love to learn more!
I know the JS engine is V8 (C++), and the rest is Rust and TypeScript, but which parts are Rust, which parts TypeScript? Why 2 languages? Is it mostly Rust, mostly TypeScript, or a bit of both?
Also, what are the hardest problems that Deno solves internally? Like if you’re working on Deno, are you mostly working on ... the dependency resolution/package management? Automatic compilation of user TypeScript code? The standard library? Something else entirely?
So, you mean the people who were supposed to make the best choices to fix server-side JavaScript with the ultimate knowledge of what's best just realized that some of their pre-made opinions are actually not-silver bullet?
At what point are people going to just admit that implementing applications in Javascript outside the browser is a poor idea?
The ecosystem has been in this poor state for years. It's not like the ecosystem is getting worse. This is the best it's ever been, and it's still horrible.
There's so many better, more mature alternatives with much better ecosystems: Python, Java, C#, Ruby, Go, Haskell, Perl... The list goes on.
The fact that 90% of your code (i.e., business logic sans OS) can run in a Chrome Dev Tools window is pretty powerful. There really isn't anything that competes except PHP on a LAMP server in 2007. The ease of "getting started" is a big part of the network effect and the number of npm packages out there. Yes, the quality of those packages is terrible, but you don't find that out right away.
Your comment is somewhat incomprehensible, because this article is not about building end user applications in Typescript. It's about building the container itself in Typescript. I switched to Node from Java a couple years ago, and to Typescript within the past year, and I have never been on a team that has had this level of productivity.
What part of it couldn't you comprehend? I understand what the article is saying. I'm talking about the dysfunctional Node.js ecosystem, which includes Typescript.
In response to your personal experience, I'll share my own: I switched from C++ to Java, to .net, to Node.js, to Typescript. Working on Node/TS I have never been on a team that wastes so much time fixing silly problems that a better language would simply not allow to happen in the first place. I have also never worked on a team that spends so much time dealing with issues in poorly written community packages, or arguing with package maintainers who could never in a million years pass a technical skills test at the company I work for.
> I have also never worked on a team that spends so much time dealing with issues in poorly written community packages, or arguing with package maintainers who could never in a million years pass a technical skills test at the company I work for.
Excuse me for asking the obvious, but if they would never pass a technical skills test at the company you work for, why are the people who did pass using code that these maintainers wrote?
It sounds like the right approach is to sidestep them and fork the project yourselves. That way you'd clearly have a much more competent team maintaining it, and implementing all the features you need.
That is if you trust code written by someone of such standards in the first place. Really you should just rewrite it from scratch so that you know it's never been touched by anyone not at the competency level of your elite squad of code monkeys.
> I'm talking about the dysfunctional Node.js ecosystem, which includes Typescript.
Deno is, by definition, not Node.js. Typescript can live outside of Node (like when it's compiled for and runs in the browser). So I think you're getting downvotes because it reads like a generic rant about the same things we've already heard about in a context where it doesn't apply. I'm not going to argue with the notion that Node has many poorly written community packages, it does, but this core piece of Deno functionality does not use any.
I will say I don’t quite feel as strongly about CSS pre-processors like SCSS, which I really enjoy, however I still prefer plain old CSS for the same basic reasons.