
How we failed, then succeeded, at migrating to TypeScript - drob
https://heap.io/blog/engineering/migrating-to-typescript
======
AriaMinaei
I was looking at some of my old repos today. Enjoyed the nostalgia. Lots of
CoffeeScript there. I had to switch to ES and then TypeScript because
CoffeeScript was abandoned at the time and I was stretched over other projects
to be able to help maintain it.

Reading my old code, I was surprised by how _clean_ it looks. How easy it is
to digest. There is a certain sense of calm when your brain doesn't have to
process all the visual clutter of a C-style syntax. I miss that.

I wish I didn't have to choose between CoffeeScript and TypeScript.

TypeScript first and foremost is about type safety and tooling. Its
architecture is largely syntax-agnostic. It operates on the AST, so the parser
and code generator can be swapped for a different syntax.

CoffeeScript is all about syntax and does not (and should not) concern itself
with most of the semantics.

They could theoretically be used together if TypeScript simply allowed custom
parsers/generators/formatters to be plugged in.

This would work with ESLint and other JS tooling as well. I did a POC on that
a few years ago [0].

[0]
[https://github.com/gkz/LiveScript/issues/821#issuecomment-18...](https://github.com/gkz/LiveScript/issues/821#issuecomment-183640299)

~~~
sa46
> How easy it is to digest

I’ve not had this experience. I’ve found the ambiguity in coffeescript a
maddening adventure in syntax confusion.

\- function call syntax doesn’t need parens except if a 0 parameter method

\- commas are largely optional both in arrays and function parameters. How do
you parse: [f, f(), f a b c]

\- implicit returns are a terrible idea.

\- the @ syntax refers to either a ‘static’ method or an instance variable
depending on the context.

\- I have to do a double take for the object literal syntax every time

~~~
AriaMinaei
Don't want to invalidate your experience. For me though, I rarely struggled
with ambiguity.

> function call syntax doesn’t need parens except if a 0 parameter method

Function call syntax doesn't require parens so to make multi-line calls
punctuation-free. Especially if some args are objects.

> commas are largely optional both in arrays and function parameters. How do
> you parse: [f, f(), f a b c]

Well commas are not optional.

> implicit returns are a terrible idea

They're especially elegant in writing declarative code. It takes some getting
used to though.

> the @ syntax refers to either a ‘static’ method or an instance variable
> depending on the context.

Agreed.

These are all tradeoffs though. For me, they struck the right balance between
ambiguity (very little) and expressiveness.

LiveScript in comparison was much more sugary (which I preferred):
[https://livescript.net/](https://livescript.net/)

~~~
k__
Haha, yes. LiveScript should have won. It were awesome times.

Well, guess it's Reason for me now :D

------
davidjnelson
> The most important realisation we had going into this renewed effort was
> that a successful migration has to be centered around people, not just tech.

Key insight. It’s always people first, code is a far distant second. Love Kent
Beck’s series on this, so insightful
[https://medium.com/@kentbeck_7670/software-design-is-
human-r...](https://medium.com/@kentbeck_7670/software-design-is-human-
relationships-part-3-of-3-changers-changers-20eeac7846e0)

Great read, Heap team! Thanks for sharing :-D

~~~
EdwardDiego
I routinely bore people with the Abelson quote that programs are written for
humans to read and only incidentally for computers to execute.

------
seieste
Typescript seems to be approaching C++ levels of syntax and expressiveness.
The main difference seems to be the existing tooling, tutorials, libraries,
etc for node.js and others.

But if compiled languages like C++ or Go had as many dedicated libraries for
webserver management as JavaScript, would there really be a benefit to using
Typescript?

~~~
throwaway_bad
> Typescript seems to be approaching C++ levels of syntax

I've been a bit traumatized by C++ so I can't help but see this as a bad
thing.

A lot of the insanity in C++ is because template metaprogramming made a lot of
micro-optimizations possible. You can use CRTP to achieve static polymorphism.
You can use SFINAE for tag dispatch to choose a different algorithm at compile
time. You can even fold entire algorithms down to a constant with constexpr.

This is great if you care about low level control of your code, but this is
usually premature optimization in the JS world.

Luckily typescript will be immune to this because the types can't affect
runtime at all. So far I haven't seen any truly monstrous generics that are so
prevalent in C++.

~~~
desert_boi
There's some Typescript type stuff that can probably get close.

[https://stackoverflow.com/a/47914631/1924257](https://stackoverflow.com/a/47914631/1924257)

[https://stackoverflow.com/a/53229857/1924257](https://stackoverflow.com/a/53229857/1924257)

~~~
morelisp
I don't agree - the TypeScript code you link is "complicated" because it's
modeling complicated types, or implementing higher-order types which need to
handle complicated types. And honestly it's not that complicated - an
explanation of what RecursivePartial must do maps closely to the type
expression ("each key of the partial type is optional, and each value's keys
are also recursively so").

This isn't at all close to CRTP or SFINAE, not just because TS/JS lacks the
dispatch features necessary, but because in both cases you link it's still
just about type declaration. CRTP and SFINAE are both ways to hack the type
system to _run_ differently.

------
gingerlime
We’re now considering switching from coffeescript to ES6 (or maybe also
Typescript). But coffeescript is seeing a bit of a revival, and I’m starting
to wonder if we should stick with it?? Tooling seems a bit behind and also
lacking things like tree shaking etc (??). But coffeescript is so clean and
fun...

Any tips/thoughts??

~~~
eropple
YMMV, but I’m less worried about “clean and fun” and much more worried about
_rugged and correct_. TypeScript makes it easier to unambiguously express
intent both inside an application and when talking to external modules. Some
parts of the syntax are unfortunate but I care about that a lot less than I do
not having my systems break.

I’d switch and I wouldn’t look back. I _did_ switch my focus of learning and
use, albeit from Ruby and Kotlin (which is better than nothing but nominative
typing is insufficient IMO) to TypeScript, and it was among the best decisions
I’ve made in my professional career.

~~~
The_rationalist
What do you think about nominal typing vs structural typing? My friends that
have been only used to statically typed, nominal programming languages, thinks
this is the worst feature of TypeScript.

~~~
eropple
I don’t hate nominative typing but TypeScript has definitely coached me
towards thinking more about data and operations on data. It does a lot to
encourage you to move away from the traditional OOP patterns that make most
people dunk on Java.

If I had to directly compare the two I think nominative typing is superior
only in the case where you have two identically-shaped (down to the property
name) classes that have different semantics. I feel like if you are in this
situation you should take a very large step back and re-think your decisions.

------
RangerScience
AFAIK, Ruby is the only language that people make other languages look like
(CoffeeScript) and JS is the only language that people make look like other
languages (CS, TS).

Are there others?

Edit: Well, I guess the JVM would be considered another?

~~~
phamilton
Lisps exist on all the runtimes. LFE (liso flavored Erlang) is a good example.

~~~
greggyb
Don't forget Hy and Clojure (which pop to mind, but I don't intend to be
exhaustive).

------
Scarbutt
_Yes, we were adding TypeScript code, but we were adding CoffeeScript at a
faster rate_

So the devs were able to iterate faster with CS than with TS?

~~~
breakingcups
Another interpretation would be that a majority still picked Coffeescript out
of familiarity and interop issues in their specific codebase. Iteration speed
could be comparable or better in Typescript too, we don't know.

