Hacker News new | ask | show | jobs
by temporallobe 2204 days ago
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.

17 comments

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.

[1]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported...

Unfortunately their jsdoc stuff only exposes a subset of their typing capabilities, so you're leaving some advanced type goodies on the table.
They've been adding features on every release for at least a couple releases. Not sure when you last checked, but regardless, it's getting better.
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.
I much prefer JS+JSDoc over Typescript when writing my own code. Typescript makes me feel overly constrained.

Also, I've been doing web dev for 25+ years now and I don't like the trend backward to waiting for code to "compile".

Although if you're going to have to compile, Svelte looks like a nice middle-ground.

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?
He's referring to https://www.typescriptlang.org/docs/handbook/release-notes/t... rather than boolean coercion.
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.

Bsb is also faster than tsc.

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.

The way it deals with async/await also seems pretty tedious.
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.
I can make them use typescript more easily than I can make them good developers, I guess ...
Enforce shared ESLint rules on commit, and use Airbnb+React with most of the defaults set.
a sufficiently complex linting process is a transpiled language, with the same downsides
I would advocate for as much simplicity as possible then. :)
How would that catch a misspelled prop name?
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.

linting wouldn't, but if you're writing unit tests, that kind of problem would be caught pretty quickly.
This also works in TypeScript's favor. Meaning you can skip writing tests that simply check you're giving the correct props.
I don't think anyone /does/ write tests that simply check they're giving the correct props. They write unit tests, and props are part of that.
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.

Instead of writing types, you write tests.
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.
Yes, you have the illusion of type safety but all you need is a slightly different JSON from an API to realize that typescript isn't that interesting.
Eslint + a rule for propTypes. Simple!
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.

Why? ES6 has been widely supported for quite some time now.
> ES6 has been widely supported for quite some time now.

ES6/2015, sure; ES2021, though...

For the latest useful JS features, you need a compiler, whether it's TypeScript or Babel or...

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.
IE11, unfortunately, isn't _quite_ dead yet, and ES6 is definitely not the last word in useful JS language features.
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.

> This cones as no surprise to me

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.
>I check types all over

Which is something you rarely need to spend time on if you're using TypeScript.

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.
Lindy effect

https://en.wikipedia.org/wiki/Lindy_effect

Transpilers definitely aren't Lindy. CoffeeScript, GWT, Elm, among others form a huge graveyard of de facto defunct languages targeting JS.

Typescript has been around since 2012. Going by the quote, it is likely to still be around in the next 8 years.
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).

I don't understand. So in 2016, Typescript was around for 4 years so it only had 4 years left, yet here we are.
its 'at least another X years'

so in 2016 typescript was around for 4 years, and here we are now 4 years later. its still around. seems to be holding.

I find TypeScript incredibly useful in reminding me my code is terrible. I use it to save me from myself.
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.
Erring on the side of simplicity is a good rule of thumb. Sometimes the simpler thing to do in a million-line codebase is to statically type the code.
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.

Same here, exactly for those reasons.

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.

I think that'd be super cool.

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.

> 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.

What runtime are you using that you can't run ES6/2015 natively in the console?

Have you used TS? Calling it a DSL seems incorrect.