Hacker News new | past | comments | ask | show | jobs | submit login
How an Anti-TypeScript “JavaScript developer” like me became a TypeScript fan (chiragswadia.medium.com)
189 points by chiragswadia on March 2, 2021 | hide | past | favorite | 392 comments



> I always felt that adding types to the functions/variables and satisfying the TypeScript compiler is an over-engineering and not providing any meaningful benefits.

I honestly find this attitude horrifying. I'm glad the author was able to move on from this, but it is utterly pervasive in some parts of our industry.

As far as "engineering" goes, specifying your types is about as low-hanging, basic a step as you can take. If this is "over-engineering" then I think that says a lot about how much thought, design and engineering goes into some of these code bases.


This comment and many others in this thread seem to be missing something. I see a lot of anger here or blame on the author for deliberately choosing to not use types, but I think the author actually does a very admirable job explaining what's going on in their head:

"... concepts like Generics felt very hard to understand ... every piece of code is strongly typed and overwhelming. Even simple code like below scared me ..."

The author isn't claiming to have had an informed opinion of types. They're saying that they found learning about types to be difficult and stressful. That's a real problem that I think people who understand types forget.

> specifying your types is about as low-hanging, basic a step as you can take.

No, absolutely not. Learning an entirely new syntax, static semantics, and entire way of reasoning about code is about as high-hanging as you can get. Sure, once you know how to use static types, applying that knowledge is fairly easy. But it's a big mountain to climb before you get to do that.

This is the key advantage of dynamic types. You can make a computer do useful things without having to invest the large effort required to learn how static types work.

Now, personally, I think it is worth learning that. And, certainly, once you learn it, you get to amortize that benefit through the rest of your career. But there's a lot of people standing at the base of the mountain, realizing only how far they have to climb with no idea of the view they'll have once they're up there. Those people deserve sympathy, understanding, and encouragement to climb. Not criticism and mockery like I see all over this thread.


Not the parent, but I think it's possible to simultaneously believe two things:

1) It is completely understandable that, considering how easy it is to for a new programmer to get started in a dynamically-typed language (and that those languages are pushed very hard as beginner-friendly), many developers have a hard time grasping the idea of static typing and how to apply it to code, because their mental model just never included that, and changing mental models is hard for everyone.

2) It is absolutely horrifying that this is the state of new-developer education (or the lack thereof) in our industry, and I would put this on the (long) list of reasons why software in general is so unreliable.

I give the OP a lot of credit for writing about his journey, and by doing so making himself vulnerable to criticism. And it makes me really happy that he was able to not only eventually see the benefits of typing, but concretely articulate some of the benefits he found helpful[0]. That, IMO, is a sign of a solid developer who is willing to expand his skills and change his mind when given new information. But from a structural standpoint, I wish he had better mentorship when he started out and had never fallen into the "typing is bad" camp in the first place.

[0] "Making impossible states impossible" is something that I sometimes still struggle to impress upon developers with years of experience under their belts. The compiler is there to help you and catch your mistakes before you even check in the code, if you give the type system enough information to do so.


In the end, and in the big picture scheme of things, what is programming about? It's about providing value. There are plenty of systems and tech built that do not use types, yet they do provide value. And those systems may seem horrific to you, but none the less they provide value. These systems were built by hacking/mashing things together, but the fact that they work, still remains. You might hate for example WordPress, but it powers tons of web and those websites might not exist if it wasn't for WordPress.

Imagine a case where you can start to be productive with WordPress within few months, but if you were to learn the whole thing, it might take few years, the value provided would be a lot lower.

I went 4-5 years of my career without knowing anything about types, yet I believe I was able to provide software that benefitted the world.

It's not that black and white.


>The author isn't claiming to have had an informed opinion of types. They're saying that they found learning about types to be difficult and stressful. That's a real problem that I think people who understand types forget.

Respectfully, its really hard for me to wrap my head around this mindset.

When I wrote my first line of code, almost 10 years ago, one of the very first concepts I learned was types. You know the basic OOP lessons where they teach that a Dog is a type of Mammal which is a type of Animal, etc. Typing was ingrained in me before I wrote any meaningful code. So from my perspective (and the perspective of anyone who learned similarly), typing is basic, foundational knowledge, and programming without an understanding of types is akin to running before you can walk

I think a lot of the developers learning nowadays are learning to code only on JS. And on JS you can do a lot without ever thinking about types. So they get stuck in the mentality that typing isn't necessary, and don't ever put in the effort to learn types.

Learning about types isn't that hard. But if you've been conditioned into thinking that typing is esoteric (perhaps due to modern coding courses completely glazing over types), then you're likely going to find it very challenging.


I've been thinking about this (and will probably try to put together an essay about it at some point). I think that the types you learn in programming 101 and the advanced types (the kinds of things written about in type theory books and papers) are related, but different beasts.

If we drop down to the lowest level, basic-programming-types are about one thing - interpreting what is otherwise a pile of bits in memory. Without any notion of the difference, how would you interpret the difference between characters and integers and floating points? There is nothing about the ones and zeroes to tell you. So the first thing you learn is to write something like `char a = 'b';`

Dependent types (and related type theory constructs) do get used for this in languages built from the ground up with that as a theoretical foundation, but they have their basis in ideas that are more related to formal verification and logic.

And that's where the divide comes in.

Using types to pick a codec for some bytes and using them to verify systems are very, very different mindsets.

And we simply call both "types".


That's an excellent point. "Do we interpret these 8 bytes as a 64-bit integer or a double-precision floating point value?" is "typing", but it's hugely different from defining a typeclass that describes a monad and then implementing it for a list type.


> Respectfully, its really hard for me to wrap my head around this mindset.

> When I wrote my first line of code, almost 10 years ago, one of the very first concepts I learned was types.

Well, that's great for you. When I wrote my first line of code, almost 20 years ago, the first thing I learned was string interpolation. Then a long, somewhat embarrassing course in what happens when you interpolate strings that weren't of the same "type". If you're introduced in any kind of self-taught way to programming, and you start with dynamically typed languages, you're doing stringly typed stuff.


A move at my alma mater to switch the introductory course from Java to Python was criticized on the same grounds. The students had a hard time in successive levels of coursework.

It seems to be a lot harder to get people who learn dynamic typing first to learn static typing, than the other way around.


It's dangerous to assume that the same number of people will continue programming if you start people on dynamic vs static typing. Maybe the static first programs weed out more people?


The anecdotal information I heard was that in general there were less people adjusting to later coursework successfully, in absolute numbers.

From a pedagogical standpoint, if the point of an undergrad education was to produce people with well-rounded abilities in their field, I don't know that switching introductory courses to Python was the best move.

Personally, I'm thankful that the first program I was enrolled in allowed me to "fail" fast, so that I quickly figured out that I shouldn't really waste more time and energy into the program and switched into CS. It's a lot easier to pivot as a freshman in your second semester than as a junior finishing the academic year. (And I knew people who took that long to switch majors, who either spent way more time and money or dropped out.)


> When I wrote my first line of code, almost 10 years ago, one of the very first concepts I learned was types.

Lucky for you. Not everyone did.

It's very hard to remember what it felt like to not know something and likewise hard to remember how hard it was to learn something once you do.


The opposite for me. Typing makes zero sense. I know what I'm doing with my variables so why do I need to specify a type? Why can't the computer figure this out? Isn't that what computers are good at?


Well, as the author of the code, you should be able to tell the function what type of variable you expect (string, int, or business entity e.g Book, Bookstore).

That way if you later try to call the function passing an int when it expected a Book, you have an early warning system at compile-time. Not run-time.


The evidence from a whole lot of code written by a whole lot of people seems to indicate that, for the most part, a given developer actually may not know "what [they're] doing with [their] variables".

For everything else, there's type inference.


The computer can indeed find out. Most statically typed language can infer types nowadays.


Python has this: https://github.com/google/pytype

"Pytype checks and infers types for your Python code - without requiring type annotations."


> This comment and many others in this thread seem to be missing something.

I think they're also shoehorning their experiences. Some coders are cogs in giant tech companies that emphasize code quality, others are on teams in large business in an unrelated field, others are solo hobbyists, and still others are the only tech guys at their medium or small business. Some write code to run a business, others write code to probe the mysteries of the universe. Some write life or death firmware that'll survive for decades, others create landing or promo pages that will be deleted next month and are subject to the whims of the marketing department. Those are all vastly different contexts for a programmer and each requires its own set of trade offs vis a vis typing.

For example, I couldn't care less about strong vs weak or static vs dynamic typing at my current frontend job because the stakeholders don't know what they want, stuff changes rapidly, and there's little I can reuse from one request to the other but I was a full blown static typing crusader at my last job where I worked on a payment system that had to deal with schizophrenic regulations.


> I think they're also shoehorning their experiences.

Yup, agreed. I first learned to program in the late 80s (when I was around 7 or 8 years old) using BASIC, and my first part-time programming job in college was a mix of C and Java. All of my EE and CS programming coursework was done in C, C++, or (pre-generics!) Java.

It is really hard for me to put my feet in the shoes of someone who switched careers in their 20s or 30s by joining a bootcamp that teaches node, HTML, and CSS, and helps them find web dev jobs.

Their journey is so different from mine that I have very little ability to guess as to what should be easy or hard for them to do as they grow in their career.

Having said that, I still do believe that everyone who wants to write code should learn about static typing eventually, and the sooner they're introduced to the concept, the easier it will be for them to integrate it into their mental model of how software works.


I switched careers at 33 (currently 35) from structural engineering to a full stack JS career after attending a bootcamp.

Reading your comment, I wish I was in the former group of learning to code early on, taking CS and SE courses in university, etc... I work feverishly to learn as much as I possibly can about networking, Linux, hardware, SQL, etc.. along with all the JS related topics I need to learn for my job.

I just wanted to add to the conversation by saying that there are people in the later group who really want to become well rounded and not just be JS developers.


> This is the key advantage of dynamic types. You can make a computer do useful things without having to invest the large effort required to learn how static types work.

That's one key advantage of dynamic types, but it's not the only one.

Sophisticated dynamic type systems like Julia's are difficult to model statically. Some idioms would require dependent types if they're even possible at all.


Yes, there's historically been cases for dynamic typing that went beyond "writing type annotations is hard", although as time has progressed, computers have gotten faster, and compilers have gotten better, the scope has gotten smaller and smaller. (I think a language in Python's niche that was created today would have a simple type system with extensive inference, just because someone developing such a language today would find it technically feasible.)

Another case is what Alan Kay calls "extreme late binding" in a messaging-oriented language, as seen in Smalltalk and Erlang.


> I think a language in Python's niche that was created today would have a simple type system with extensive inference

How do you think a “simple type system”, suitable for a Python-like language, would look?

The type systems that have been developed for Python itself, for example MyPy, are far from simple.


>The author isn't claiming to have had an informed opinion of types. They're saying that they found learning about types to be difficult and stressful. That's a real problem that I think people who understand types forget.

I don't understand how one can be a great (or even half-decent) SWE with such an aversion to learning something so common and foundational as types.


After working in the industry for many years, I have aversions to learning many things. Usually, it's clearly a failed recycled idea with a small twist, poor approach to a problem, or someone selling new shiny.

I have no aversion to learning something when it shows potential value, but you must explain the value without gimmicks. Maybe typing hasn't been well sold to this person. The new thing I learn should make my life easier, not harder. If you don't apply a filter, cargo cult and marketing nonsense will sweep you away in a world hidden in unnecessary complexity to make a few bucks.

If learning and using something new adds more stress and difficulty and little-to-no benefit than life without it, I'll pass. When it comes to typing... I don't think that's the case. Typing can be annoying when you first use it (I'm sure I complained a lot) but it's well worth it when you need a stable maintainable codebase.


I get your point, but I think it's misplaced. Types are not new, in fact from a CS perspective they are very old.

I think it's a shame that learning about (even just basic) types is being taught as some new thing that can help to make your code better, rather one of the fundamentals that we should be learning from the beginning, which can still provide benefits even when writing in dynamically typed languages.

Perhaps it's just a case of bad marketing and lazy educators.


I'd be willing to bet money that if you were to list all your skills and non-skills, I could find at least one thing that you don't know that other SWEs would consider just as "common and foundational".

Could be any of: data structures and algorithms, complexity analysis, operating systems, parsing, compilers, databases, networking, user interface programming, OOP, FP, MVC, markup languages, the web, graphics, manual memory management, pointers, computer architecture, etc.


Around the world millions of people learn Java as their first programming language. It is not hard to learn how to use types or generics.

What appears to be difficult is to go from an untyped language to a statically typed one. Which is why everybody should start with a statically typed language so that the psychological barrier never develops.


This is wrong. Dynamically typed languages still have types that need to be understood by the developer. They are only checked at runtime and not at compile time.


Values have types, but variables do not. All programmers have to think about the former, but only statically typed programmers need to reason about the latter.


> a very admirable job explaining what's going on in their head

As someone who followed the author's path, this is spot on, and also what I recognized in the article. Everything else you said is spot on too, I just wanted to call this out as part of the article's would-be audience.


> They're saying that they found learning about types to be difficult and stressful

No, they're saying that types (which they don't understand) are "over-engineering". This is, frankly, not acceptable to me.


They're describing how they felt before learning about types.


Yes. Like I said.

> I'm glad the author was able to move on from this, but it is utterly pervasive in some parts of our industry.


It's entirely possible you have a language barrier, but you should know that there's a meaningful difference between past and present tense when you're representing what other people said.

(Edit: added clarification of which speaker's tense was important)


I did one of my internships at a financial services company. Their web applications were responsible for performing transformations on massive JSON datasets, with a huge variety of financial data. This is precisely the kind of project that would benefit most from typing.

I was relieved to find out that they were smart enough to use TS, yet horrified when I looked at the code base and found that the entire codebase was littered with the "any" keyword, making typing damn near useless.

We had so many bugs reports that essentially boiled down to "this data is being transformed in a way it shouldn't be". Almost invariably these bugs were due to the developer thinking that some variable represented one thing, when it really represented something else, and they thus performed an incorrect transformation on it. Typing would've eliminated this entire class of bugs.

Figuring out what any variable represented often involved traversing the huge codebase to find out where the variable originated. On some occasions, I even had to talk to the back-end developers to figure out what the heck was going on. Typing is self-documenting, and would've completely eliminated the need to go on a scavenger hunt to figure out what a variable meant.

Anyways I got sick of this rather quickly, and made sure to add types to any new code that I wrote. I was the only developer on the 20 person team that bothered to do so.

As an intern, I didn't understand why these developers refused to use types. I just assumed that with their years of experience, they must've had a good reason. Now looking back at it, it's clear that they didn't understand types, didn't want to learn how to use types, and thus just chose to completely ignore typing.

As you said, this is utterly horrifying (especially for a financial services company dealing with real money).


I've had a similar experience. My team is using Vue 2 and, while the VueX store is almost entirely correctly typed, inside the Vue components everything was typed as 'any'. There was no value being added in the slightest, but attempting to upgrade packages resulted in many new TypeScript and ESLint errors.

I ended up opening a PR to strip out TypeScript from all the Vue components so I could get things up to date (and ease a possible transition to Vue 3, which behaves much better with TypeScript).

I'm starting a new job soon and really hope I can work with React and TypeScript again.


I have a personal project ive worked on a lot last year. There was a part in my code which at the time scared me a bit because of the complicated data organization and manipulation that was going on. When I first wrote it, I had to have a clear picture in my kind about what properties an object had and what their properties had and do on. I had to write this down all on paper.

This year, when I came back to the code. I converted everything to typescript. I made sure that every variable that my manipulation worked on had a type. It not only helped me remember how the code worked but it made it so much easier to understand it and modify it without fear of breaking things.

It's been super useful and I don't think I'll be writing any big programs in the future without it.


JS the language isn't great but it's JS the culture that is the real problem.

There is a subset of JS codebases that are good, well engineered and written by people that understand the languages faults and limitations but the list is incredibly small and even smaller still now Joyent isn't really around anymore.

If there was one ecosystem I wish I never needed to touch again it would be JS but unfortunately it's become so pervasive that isn't really a tenable position anymore.


> JS the language isn't great but it's JS the culture that is the real problem.

This is the money quote of the thread for me. From the perspective of someone whose main language has been JS or TS for about 8 years, it's getting worse since some of the biggest names in the discipline just seem to be people with large social followings giving terrible advice. This advice is then eaten up by hoardes of bootcamp alumni who have been given a loose understanding of React and unleashed on the world as "junior developers".

But maybe I'm just cynical.


Its not just bootcamp alumni, frontend is filled with people with 15 years of experience who were sitting in some shop before the frontend boom basically being a jQuery engineer and never actually learning about software design, never mind basic computer science concepts. Then the boom came and now these types are managers and senior engineers who only know how to talk about "which framework?" as far as design goes and who are eager to call any other discussion as over-engineering.


The fact that it's getting worse says to me that we're just returning to the human mean. For decades programming was seen as the purview of nerds and geeks so the only people who turned to it tended to genuinely like it and master their craft as much as exploit it. Now everyone and their grandma use software so programming has become one of those semi-prestigious professional career paths but without the crazy expensive barrier to entry or restrictions in supply that doctors, lawyers, etc have. Even though programming is largely problem solving and "intellectual" rather than menial physical labor, the field has become so accessible with the internet that the distribution of engineering ability is starting to look a lot more like the usual bell curve centered on "just average".

It was great while it lasted.


Curious if you can share some examples of this bad advice?


It's the same thing with PHP (and Ruby). You can write reasonable code in it, the problem is that the engineering culture leaves a lot to be desired.

In Java, the engineering culture is strong but stagnant.

Python is toxic, it's full of scientists, the engineering is bad (but a little better than PHP because the community is of a higher calibre).


PHP's type hinting can be a nice onramp to typing, albeit runtime checks. With some linters it can be the best of both worlds for those disciplined and educated enough.


>JS the language isn't great but it's JS the culture that is the real problem.

I'm happy you bring this up. Us developers have a tendency to blame bad code on poor tooling/languages or on individual developers or organizations. Not enough attention is given to cultural factors within various ecosystems that systemically induce bad coding practices.


Also worth mentioning that the tooling and language follows the culture to a degree.

Java has incredibly high quality tooling because the engineering culture demands it. (also they tend to pay for it which creates a market. I myself pay maybe ~$400/yr total for my professional tools, Jetbrains Toolbox, Yourkit, etc)

The changes to the language and runtime also follow from this.

I would say Java and it's periphery ecosystems show the most promise in 2020 bar maybe Rust. There is also great things going on in C#/.NET space but I'm less involved there than I was previously so can't speak to how fast it's moving.


In the movie Minority Report, there is a scene where the protagonist is blindfolded and opens a fridge that contains one fresh and one spoiled version of each item.

Eventually, he bites a spoiled sandwich with mold and drinks spoiled milk.

That is the best analogy for npm.


> As far as "engineering" goes, specifying your types is about as low-hanging, basic a step as you can take.

How do you come to such a conclusion when there have been many languages whose success was specifically tied to the fact that they were dynamically typed? Doesn't that indicate a pain point?

> If this is "over-engineering" then I think that says a lot about how much thought, design and engineering goes into some of these code bases.

"Over-engineering" means drawing blueprints when the job is to change a bulb. It does not mean that blueprints are useless. It's about the job and the tools picked to do it. I can conceive of many jobs that fit the scope of a dynamic language and where bringing the big typed cannons could be seen as over-engineering.


> How do you come to such a conclusion when there have been many languages whose success was specifically tied to the fact that they were dynamically typed? Doesn't that indicate a pain point?

The pain point was always tedium, not difficulty. At least that's how it was sold. We haven't seen a new major dynamic language since type inference went mainstream (and existing dynamic languages are putting a lot of effort into enabling static typing), and I don't think that's coincidence.


> there have been many languages whose success was specifically tied to the fact that they were dynamically typed

Language success does not mean product success. A language is just one of the many things in your toolbox. There's a reason why when many products grew larger, they all are migrating to statically/strictly typed languages.


> How do you come to such a conclusion when there have been many languages whose success was specifically tied to the fact that they were dynamically typed? Doesn't that indicate a pain point?

How do you come to the pain point conclusion about static types, rather than prior art static type systems, when the vast majority of tooling around the most popular dynamically typed language explicitly dedicates resources and visibility to its most popular static type system?


I've worked with a lot of people in the Python world who just wanted to move tickets across the kanban board as fast as possible, and they'd do a quick check of the happy path and call it a ticket. They'd be praised for their output and we (rightly, I think) didn't try to trace bugs back to a developer. They would do all sorts of dynamic-typing hacks to get the immediate task at hand done with little regard for the mess that was made, and they strongly disliked static types because they made those error prone, unmaintainable hacks really difficult to express.

Let me pull that out into a block quote:

> [types] made those error prone, unmaintainable hacks really difficult to express

This is, in my mind, the most valuable feature of static types, and one that at least some dynamic typing enthusiasts can't easily get their heads around. Types are like rails that guide you to code which is maintainable. Another very valuable feature is that they serve as documentation that would otherwise never be written or quickly fall out of date in a dynamically typed language. Lastly in importance is that the compiler/type-checker precludes certain errors.


I worked on one of those code bases. The team thought fixing endpoints where the ORM was being used incorrectly and generating N+1 queries was "premature optimization."


The term "premature optimization" has been weaponized in the industry at large. Especially in front end development. And it really, really shows.


I'd say that's only partly true.

Even at large companies, there's often pressure to deliver quickly and often. Throwing out large parts of the UI and starting over to please the marketing department is SOP at a lot of places too.

If it were a normal desktop application, they would throw a 30-man team at the problem, but because "it's just a web page/site", it'll be a team of 3-5 people and the time tables will be pushed up.

When you combine these problems, it's no wonder that a lot of JS devs view almost anything that isn't a new deliverable as overly-optimized.


It's especially ironic considering the source of the phrase:

> Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. -Knuth

It's like that cliche "it's only a few bad apples" from the proverb "a few bad apples spoils the bunch."


Yikes. The only way I could imagine this being okay is if N is bounded and small, or if the DB is SQLite.


I think one of the sources of this kind of attitude is experience with type systems that are clumsy or slow to use. This goes equally for languages without type declarations and those with.

Personally, the two things I informally look for are:

* Does the language allow instant-to-a-human static analysis so I can see warnings when I'm passing the wrong type to a call?

* Will this language allow me to leave sections (almost always something I get off the wire) with minimal / no type information in order to come back to it later?

Typing is hugely powerful for avoiding problems. I've done a lot of work in Python, which I think has missed huge opportunities to introduce a more robust type-checking system. My current favorite is Elixir / Erlang, which I think uses pattern matching and static analysis to balance strong typing v.s. weak typing wins. It's interesting to compare Elixir to Elm. Elm has a much stronger type system, which means I almost never pass the wrong thing, but it also makes dealing with unstructured data much more frustrating.


Interesting characterizing engineering as honestly, horrifying, low-hanging and regarding one approach to typing as translatable to all practices and the underlying assumption it conveys a guarantee of reliability. I don't find any of those things to be true (in isolation or together). Of course I only know so much so there's that.


That's true to a point but it depends on perspective. On a big team with a mix of experience levels, you are going to want to put up as many barriers to mistakes as possible and it doesn't matter how much it slows anyone down because it can't be more than dealing with the problems will be.

But less people, smaller projects, higher experience levels, and better testing are all factors that shift the balance between effort and expected return. Before TypeScript came around I wrote multiple 5-10k loc apps alone in JS and the number of bugs that TypeScript would have caught in those was pretty minimal. Working on a team of 5 on apps twice that big, I see errors that TS could catch in almost every single file.


If a majority of software developers had your attitude towards static types all dynamic typed languages (maybe except for JS) would have died out by now.

> If this is "over-engineering" then I think that says a lot about how much thought, design and engineering goes into some of these code bases.

Does that mean no thought and design went into all the huge protects like Instagram, Netflix and Whatsapp (that use dynamically typed languages)? Design and engineering is much more then just adding types. Clean design patterns, good code, tests and docs are pretty important too. In fact they are much more important then just static types.


Oh come on, this is a discussion probably older than both of us put together. And we probably both know that the discussion devolves into where/what kind of tests are written. I'm on your side in the static type system debate, but you must realize that the responsible part of the other side delegates the responsibility to exhaustive testing.


> you must realize that the responsible part of the other side delegates the responsibility to exhaustive testing.

I certainly realize it, and I've seen it once in ten years and it'd have been dealt with automatically by a compiler because they were writing tests for autogenerated code. (Why not test the generator, you may ask - and that's a story for another day.)


Typing offers guarantees. You can guarantee that your function will receive the right inputs, and produce the right outputs. Even soft typing enforced by an IDE is beneficial in that sense.

I have refactored a large, central chunk of JavaScript code back at HERE. I found and fixed several bugs related to typing as I went along.

A lot of code passed server responses or a subset of them as-is, so I had to read API documentation to understand the inputs of some deep parts of the frontend code. This is why I favour explicitly encapsulating server responses in a data class.

In addition to typing, I favour microtypes and enums. Those go further to prevent unexpected application states. Assert statements are a last barrier against unmet expectations that could break things.

If you want to build reliable software, you must be strict about the inputs you accept. Don't let sloppy inputs propagate.


"horrifying" is horribly melodramatic. perhaps sigh-worthy, but let's stop short of sensationalism.


As a c developer, I've always found the lack of typing to be one of the things I dislike about python.

If you're calling a function in C, a lot of the time just knowing the type and argument name is enough to call functions without resorting to documentation

In python, you have the argument name and then... what do you want? A number? Are floats or integers alright? Is it a string? And object? An enum? Are there any bounds on the input data that a data type would've instantly told me? Fine, I'll go read the documentation

Adding types gives you so much more information in so few characters


What C has barely counts as typing, frankly. No generics, no polymorphism at all, no sum types, even basic wrapper types are painful...


There's nothing especially "horrifying" about this.

In fact, several geniuses in Computer Science have historically been of the same opinion (pro dynamic typing).


Much of web development doesn't need extreme levels of attention to safety. A good fraction of web development is such that errors are quickly caught in manual testing and at worst just make some button look weird for the short span of time before the problem is noticed and fixed. Also, time spent using generic safety tools is time that could instead be spent reworking and better understanding the specific code to make it safer. There is a lot of cultism in the industry about testing and type safety. I have seen people demand almost 100% test coverage for code that displayed some extremely simple UX which, if it broke, would be completely obviously broken the first time you tried actually interacting with it. I have seen TypeScript used for short code that basically just displays simple UX and is made up largely of calls to third party libraries anyway. I think there is no generic appropriate level of attention to safety. It depends on the context. If you're working on code that controls a spacecraft or a medical device, it makes sense to spend an enormous amount of thought and work on safety. For much of web development, that just doesn't make sense, but organizations seem to often fall into a trap of mandating bondage-and-discipline features for stuff that doesn't need it - why, I don't know. Maybe because there's an impression that "everyone else is doing it". I guess also, some people just enjoy it.

But I don't enjoy it. I like writing JavaScript. I think I can often do it elegantly and that the perceived elegance at least somewhat corresponds to objective quality. TypeScript makes my code uglier, to my taste at least, and makes development less fun for me. This impacts not just my feelings, but also my productivity. TypeScript had better provide me with something great to make up for this. I rarely make the kind of errors that TypeScript is capable of catching or feel like I need the help with readability and code discovery that it provides. But other people, I recognize, do benefit from it sometimes and in any case, other people pay me to use TypeScript.


Types make little sense to me. I guess I'm not welcome in your world.


Types loudly state what you accept, and what you return, and possibly enforces it.

The real world equivalent is giving plugs specific shapes, so that you don't plug your headphones into a 240V wall socket.

In a large enough team, this is essential to prevent incorrect data from being passed around, and breaking further down the line after causing a lot of damage.


Types do make sense to me, but they didn't always. You're certainly welcome in my world. You're also welcome to reach out if you want to gab and learn a little about how learning static types has improved my engineering life and skills. Easy to find contact from my profile.


It's probably worth taking a step back and interrogating why the actual "Why was I Anti-TypeScript?" a little bit more and use it as an opportunity for broader self development.

The author didn't use and understand something, and rather than trying to they instead just defaulted to rejection. It's midly disapointing seeing this in people who label themselves as "Senior".


Ironically, as someone who has experience w/ both fast-and-loose JS and with "properly" statically typed languages, my beef with typescript is precisely that it allows people to be fast and loose, sometimes in ways that are not super obvious. For example:

    type Thing = {
        name: string,
    };

    function getThing(): Thing {
        return JSON.parse('{"error": "invalid id"}')
    }

    const thing: Thing = getThing(); // lie to me!
    console.log(thing.name);
This is a trivial example to illustrate the idea that it's relatively easy to make a type that cascades through a very large app but which is backed by a complete lie.

I definitely think that there's also something to be said about meta-programming yak shaving (e.g. people wasting hours trying to write a "function" that takes an enum and outputs another enum w/ a fixed prefix, when simply writing out the enums would've taken 30 seconds w/ VSCode's multiple cursor feature)

Personally, the value I see in TS is in cementing documentable facts about a system: e.g. such and such function takes such and such well-defined entity, dot not treat this `options` argument as a generic bucket for pass-through garbage.


The "curse" of Typescript is that it's built on Javascript, so you can tell it to lie to you all the time. This is the problem with introducing Typescript to a larger group of Javascript developers who arent all on board (because of either experience or being stubborn) - you still need to establish good habits and patterns for how to write typescript.

I'm working through the very lie you're showing now because the disclipline wasnt established from the start to avoid these anti-patterns. Typescript isnt the perfect magic bullet that will disappear all your problems - you still need to have good developers writing good code, but TS will make it easier.


> you still need to have good developers writing good code, but TS will make it easier

Very true. Typescript is still immensely helpful in the sense that it will complain if you pass a Thing to a function expecting a Foo, regardless of the fact that Thing is meant to be a thing but is actually an error.

But IMHO, by sticking to a decision to be lean in terms of transpiled JS, TS suffers greatly from cases like the one I showed. It would be great if the compiler enforced that these types of unsafe casts had to be explicitly specified (even if via some strictness flag), and even better if it could do a better job at refining types through runtime constructs like `if (typeof thing.name == 'string')` (it does do it to some limited extent, but not enough to cover many common scenarios, due to the curse of targeting Javascript, as you mentioned)


You can easily write your own "type guard functions" when you think TS is missing an inference from a runtime check you would like. The syntax is simple enough, it's just a slightly different return type from boolean:

    function isThing(value: unknown): value is Thing {
      return typeof value === 'object' && typeof value.name === 'string'
    }
The `unknown` type in general is still pretty new, but will be greatly helpful for cleaning up a lot of code that assumes a type or used to use `any` or `{}` because there wasn't a better type to use in that situation. The Typescript team is hesitant to change the last few cases of `any` in lib.d.ts to `unknown` directly (such as `JSON.parse`) because that would be a big compatibility breaking bug. There was a proposal for a flag to do that (treat `any` as `unknown` in lib.d.ts), but I'm not currently aware of whatever happened to that idea. I would love to see it or something like it happen.


User-defined typeguards are just fancy ‘as string’. They are not type safe.


They localize all the unsafe type casts to one place, where you can inspect the logic, though. Much better than having `as string` sprinkled throughout your code.


In the large this curse is true for everything. The difference between 8 u8s and an f64 is thin for all architectures I can think of.


This particular example is close to my heart: the definition files for things like JSON.parse() were written before the "unknown" type was introduced as an alternative to "any"

And because this "any" is coming from an external definition file, it can't be caught by tsc's --noImplicitAny nor eslint's no-explicit-any

Those two rules allow us to protect us from our own code, but not external definitions/libraries. Relevant GitHub issue here — https://github.com/microsoft/TypeScript/issues/26188


Looks like eslint is working on a new set of rules that would help with these currently-unprotected any cases: https://github.com/typescript-eslint/typescript-eslint/issue...

> Create a rule which uses type information to determine when you're inadvertently breaking type safety by using an any, potentially without knowing.

> Often libraries (or even the typescript defs themselves) can have weak(/lazy) types which return any. If you're not careful, you can inadvertently introduce anys within your codebase, leading to bugs that aren't caught by the compiler.


If you're not using a bunch of generics, check out typescript-is [1]. It takes little work to get it setup, but it generates run time type checks for you. I understand why typescript decided to not add this functionality to the core of the language, but it's starting to feel like the largest missing piece of typescript is a built-in way to generate run-time type-checks for user-defined types from just the type definition.

The happy medium we've found with that module is using the runtime type-check on anything "unsafe" to bless the result using typescript-is's equals functionality, but still allowing programmers to use casting with a comment justifying its necessity. For us our list of unsafe is results pulled from the db, anything parsed from JSON, and incoming request bodies (which can be a special case of parsing from JSON, but not always).

[1]: https://github.com/woutervh-/typescript-is


Doing runtime-typechecks really is a blessing, and it would be great if typescript would provide this as a language-feature. There are two more libraries I know which are great for that:

* Zod: https://github.com/colinhacks/zod * io-ts: https://github.com/gcanti/io-ts (for the more functional-programming-oriented)


We decided against io-ts because we'd still have to write the validator ourself (unless we used their type system as the source of truth, which wouldn't easily work for our project because we generate most of our types from an openAPI schema), which is exactly what we wanted to avoid doing.

I hadn't heard of Zod before, but i really liked the "parse don't validate" blog post linked. Turns out that's exactly how we've been using typescript-is. But it still suffers from the problem of expecting to be the source of truth and thus not working well with generated types.


I like io-ts, but I've moved mostly to runtypes: https://github.com/pelotom/runtypes

I forget why Zod didn't pass muster for me now, but I've looked at it before and didn't find a compelling reason to jump to it. Thought it seemed good, though.

I really wish at least one of these let you emit JSON schema back out, though. That'd be way easier for dealing with stuff like OpenAPI.


We go the other way. We start with openAPI, use dtsgenerator to spit out typescript types, and then use a library (typescript-is) that will generate run-time type check function as part of compilation.

A downside to this is that you need to compile type changes before you can use the change in code, but it gives us a single source of truth for our type definitions and let's us generate a more exacting request and response verification functions that use the (sometimes) more precise open-api definitions (eg a an array with a maximum number of elements and specific string formats), and it's really easy to add a run-time type check to the result of calling into a 3rd party library as well.

For runtypes, you could write a script to use its Static function to spit out the interfaces in pure typescript and then use something like typeconv or ts-to-openapi to make your openapi definition, and then use that script inside your build script to output the openapi schema.


Interesting! How do you wire it into validation, etc. for your web layer?

If you've got an example I'd love to see it. I've long been not a fan of OAS-first, but I'm always down to learn something new.


We like OpenAPI first because it's more exact than pure typescript types. I suppose there's libraries we could use to give us a similar level of exactness that would also get us typescript types and OpenAPI with similar exactness to openAPI first, but then that's another dependency that's not giving us anythign extra compared to openAPI first.

So the way we do it is a little meh because we have two separate run-time type validators, but it's because of the path we took where we adopted request and response validation almost from day 1, and other runtime validation came much later.

We're using express and express-openapi as the base of our project. Express-openapi has built-in request validation and type-coercion, and an example of how to quickly bolt on your own response validation, so for request and response validation we're using that. And it works. It's damn solid. But the docs for how to use the underlying tech to do similar run-time validation for say pulling values out of the db is lacking and I don't have enough expertise in the underlying tech to stand it up quickly, especially compared just dropping in typescript-is changing tsc to ttsc and adding an tsc plugin to our tsconfig.

If I were to do it again I'd either bite the bullet and spend the time figuring out how to get express-openapi's request validation infra to also do general type validation on just the schema, or i wouldn't use their run-time validation at all and just make my own middleware to do it, just so that I've only got a single run-time validation library. The nice thing about express-openapi is that since it "knows" the open-api definitions it can programmatically apply the types needed for validation, so rolling my own would require that functionality, because I don't want our team to have to remember to add the same middleware to every endpoint using a factory function that takes the typescript-is validator function as an argument, and the nice thing about typescript-is is that i can give it a typescript type and get a validator function exactly where i want it with no muss.

Anyway, our build looks like this: 1) compile typescript 2) compile the openAPI to a single file (we put the endpoint definitions in the endpoint file) using express-openapi (just initialize and then write out the JSON.stringify of the apiDoc field) 3) run dtsgen against the output of step 2, and pipe that through `sed 's/declare//g' | sed 's/namespace/export namespace/g'` and into some file.ts 4) compile the file from step 3 with typescript

step 1 gives us typescript compiled to js step 2 gives us a single openAPI.json file we can pass around or import into postman step 3 gives us all the types from openAPI in a ts file with a bunch of recursive exported namespaces step 4 gives us those types in a .d.ts file

We do 3 and 4 in a subdirectory so that we can publish the types as an internal package, which means we can give front-end a types package to consume for all the calls we want to make to backend. Well, we actually publish an sdk package that wraps the types and encapsulates the logic for making the HTTP request to the right endpoint, so we don't have to worry about calling POST when the endpoint is PUT or fat-fingering the response type cast through the entire front-end and can instead just call a function with well-defined types. Plus, now it's super easy to test the interface, because we have a single thing we need to test. So we write an exhaustive happy-path (ie 2xx status codes) integration test against the sdk that actually calls into backend gets the response and checks the response against the type and then the values we expect for each field.


If you have to rely on restrictively typed languages to produce maintainable code, I think that’s a different topic.

Typescript isn’t perfect by any means but it does a good job keeping code based easier to work with in a larger team. Much better than vanilla JavaScript


It's worth noting that this (good) example is unrelated to unsoundness, too -- it's related to built-in APIs using 'any'.

Within Google we include a "strict" d.ts in every compilation that shadows this API (and one other) with one that instead returns "unknown". We have talked about going through the whole TS API and removing all the 'any' in this manner for this reason.


That's a great idea! What's the other built-in that you shadow?


The definition of `new Map`:

https://www.typescriptlang.org/play?#code/FDDGHsDsGcBcAJrwLz...

(I still think this is actually due to bug in TypeScript, see https://github.com/microsoft/TypeScript/issues/31990 .)


I've always told folks that no technology will save you from your own developers.

A good application can be written in any technology, just like a bad application can be written in any technology.

Certain technologies will try to guide you to a better place, but it's up to developers to take advantage of it. Or to do crazy stuff like the above. . .


Sure, but you also should never just blindly trust a JSON.parse, and if possible you should avoid typing functions for exactly this reason, and let their return types be implied instead. If you didn't type `getThing` then its return type would be `any` and you'd get an error in your IDE on the last line.


If you don't annotate the return value you open yourself up to another class of mistakes because the compiler can't check that each branch returns the correct type, especially if type inference decides the function returns `any` which swallows `undefined` in type hints, while also losing the self-documenting aspect without an IDE.


sorry but i feel like this is backwards. the error - incorrectly assuming an `any` will be a `Thing` - is in `getThing`, and that's where the error message should be. getting an error in code that calls `getThing` instead would just obscure the real issue.

also, i think "avoid typing functions [...] and let their return types be implied" is terrible advice. argument and return types are the thing you should type explicitly, because it makes the errors local. otherwise you'll get all the fun of tracking down where that `null has no property "blah"` error came from, just at compile time


This is the one thing that bothers me about TypeScript as well. I've ended up using frameworks like `zod` to do runtime type checking of endpoints. It has gone a long way towards decreasing edge case failures -- I just wish they had something like this built into the language.


Not doing runtime checks is a deliberate decision: https://github.com/Microsoft/TypeScript/wiki/TypeScript-Desi...

So Zod it is. I like it.


Just a quick tip that helped my team with such issues:

- For every call to an API, or input from the user, there should be a few tests checking for unexpected data

This rule alone forces us to fix the majority of runtime errors such as this example (since JSON.parse() is usually called when handling an API response)


To me, the solution is simple: use a single source (some IDL format) to define objects at API boundaries and have your frontend and backend use it.

It will make it a lot harder to return wrong types from your calls. Personally, I like gRPC + Protobuf.


> (e.g. people wasting hours trying to write a "function" that takes an enum and outputs another enum w/ a fixed prefix...

Metaprogramming shouldn't suck so much that this takes hours.


You're not wrong. That's a good example of why someone might have beef with typescript. But as others have been saying, tooling enabling faster dev is one of the main reasons people use typescript. Safety comes second for most folks. And the tooling works just fine in that example.


The problem in your example isn't TypeScript. It's the JSON parser. If you used GSON in Java, you'd get the same result, despite being statically typed with runtime type checks.

You can implement the JSON parser to be type safe. For example, this is how nest-dto can prevent this.


Check out io-ts — it can take a minute if you’re not familiar with functional programming, it’s built on top of fp-ts.

Being able to encode/decode IO safely has been a huge blessing when working with JSON.


Wait... so I assume `JSON.parse()` returns `any`, yeah? TS automatically downcasts (in function returns and assignment)? How is that at all useful?


It's a historical artifact of Typescript's development. The `unknown` type wasn't introduced until Typescript 3.0 and since `JSON.parse` is part of the Javascript "standard library," changing it now would be a brutal breaking change across almost the entire ecosystem.


this seems to be an issue with bad typings - ideally `JSON.parse()` would return `unknown` and then it wouldn't lie to you, but that would probably break a lot of people's code.

EDIT: https://github.com/microsoft/TypeScript/issues/26188


This is an argument against strongly typed languages, not Typescript. You could do a similar thing in Java and C#.

I don't know of any language that can stop someone from being a sloppy coder.


It's actually the opposite. This would throw an exception in a strongly typed language. It would silently return the wrong thing in javascript because it's not strongly typed.


The point of the argument is catching errors at compile-time. Typescript doesn't make (and can't make) any guarantees at runtime.


In case it wasn't clear, that example compiles without error, whereas a more strict compiler would complain that a any is not a Thing, or some similar error.

The code doesn't even throw runtime errors, but you wouldn't be able to tell something is wrong unless a) a request providing the json string actually responded with the error string in the example (an edge case that is very easy to overlook during regular development) and you managed to catch the problem in tests, or b) you specifically went digging into the file that defines getThing looking for the implicit any cast that the compiler didn't tell you about or c) there's a compiler update that turns that any cast into an error

What others are saying is that Java and friends do c) (throw compilation errors when implicitly casting between incompatible types)


No, those languages actually enforce type checking at runtime. The libraries for parsing JS that support parsing into a custom type will blow up right there if the provided JSON cannot be parsed into the provided class, not 5 steps later when you try to use something from that class that isn't actually there.


Typescript doesn't exist at runtime.


Java would absolutely stop you from returning a JSON object when you're supposed to return a Thing. You could cast it but you'd still get a ClassCastException. Now I haven't written JS or TS, so maybe I'm not understanding what you're saying?


Just like Generics in Java, Typescript only exists at compile time. Talking about what Typescript doesn't do at runtime is moot.


Typescript permits you to write code that does implicit unsafe casts at runtime. Type-safe languages don't. Java Generics don't let you implicitly do unsafe casts[1]; erased generics mean the unsafe cast wouldn't necessarily fail visibly at runtime (though there are warnings and linters to alert you to that, and techniques to work around it), but it would enforce that it was explicit in the code (and you would then know to add extra test coverage etc.).

[1] You can implicitly do unsafe casts using arrays, but arrays aren't really using generics, they're a special-case builtin.


The example above is equivalent to gson.toJSON(string, Thing.class)

It'll just return an empty Thing right? No ClassCastException.


I think the skepticism of new shiny things is healthy. Of the set of things that exist, most things are worse than the things one already uses/prefers. Most new things solve a specific problem that may not overlap with the problems one is trying to solve. With software development, a huge part of the puzzle is tooling (as the article points out), so even if typescript is obviously superior as a language, the tooling needs to catch up before it's a reasonable/useful alternative. In this case, the tooling quality, enabled by the static typing, shot typescript way past the thing it was replacing.


Strong typing is not shiny or new and, even if you're a javascript guy, not being remotely familiar with any strongly-typed language (or generics?!) is a red flag.

(edit: red flag is a bad description, because he ended up being self-reflective and looking deeper, which is just about the furthest thing from a red flag.)


Agreed. But some people have an attitude of Strongly Typed == Needlessly Verbose. Probably because most developers have only experienced Strong Typing via Java.


I'm in neither camps (I don't have anything against types in places but I also don't try to put them everywhere). Could you explain how TypeScripts types would be more/less verbose than the types from Java? At a glance, TypeScript looks a bit more flexible, but mostly the same.

Then Java is a verbose language in general (forced directory structure, one-class-per-file and yadda yadda) but that's besides the point as you're pointing to TypeScripts types being less verbose than Javas.


1) TypeScript has local type inference, meaning that `let x = returnsComplicatedThing();` will work, where in Java it would be `Complicated<Generic<Type>> x = returnsComplicatedThing();`. (At least up until the last few years)

2) TypeScript has type aliases, meaning you can write `type MyTable = List<Map<string, number | string | Foo>>` and not have to repeat yourself everywhere.

3) TypeScript has anonymous unions and tuples, so instead of writing `Triple<Integer, String, Foo>` you can just write `[number, string, Foo]`, and likewise instead of `OneOf<Integer, String, Foo>` you can write `number | string | Foo`. These are also built in and very ergonomic, so you don't have to write a OneOf4 class whenever you want to have one of 4 things, and you don't have to write helper methods to convert between different sized OneOfs.


Don't know about the other two, but the first one is available in java 10 and later.


Worked on a project with an old (12+ years?) - but still being developed/used - Java system. Just last year a move was made up to Java 11 (from 8). Decent test coverage, but moving multiple systems is still a big task, but... they did it. Java 11. Yay.

But... teammates were running in to issues with 'new' stuff - like, using 'var'. There were others, but this was sort of the archetypal argument. "Well, it doesn't match the rest of the style of the file/app - it'll make it hard to read". Well... hrm... any new feature literally doesn't match the style of what came before it, because you have new keywords/features/syntax to handle processes a new way. It's definitional. But just because there's a new feature doesn't mean it'll be adopted (for better or worse, I supposed, depending on your stance).


Java-the-language/JVM has picked up pace hugely in the last few years, but Java-the-ecosystem tends to lag quite severely. Not least because these systems tend to be entrenched systems that move quite a lot of money around... or are highly business critical in some other way. This leads to extreme conservatism wrt. upgrades, etc.

(That part has also gotten better, but especially the Java 8 -> anything later upgrade has been extremely painful because of modularization. Past Java 9 it usually isn't that much of an issue. However, JDK 11 was the first LTS release after 8, so most shops basically delayed the transition until JDK 11.)


This BS made me want to tear my hair out:

    VerboseTypeName foo = new VerboseTypeName();


The reading or the writing part? The reading is easier with explicit types. The writing is a non issue considering tooling auto completes the second instance almost always. modifying later can be cumbersome but the tooling makes it somewhat easier too.


Both, and not interested in tooling to help me repeat things. :-)


Strong typing can be both needlessly verbose and useful, or the total opposite. My experience with java compared to Typescript, is that the tools largely compensate for Java's verbosity, while that is less true of TS or JS. For example, generating strongly typed method definitions from field declarations.


This, and usually Java from 10-15 years ago before the `var` keyword and diamond operator.


I definitely fell in this camp. To be fair I was fairly junior and was used to JS.

It wasn't until I started using Haskell that I saw the benefits of knowing exactly what I was working with. It also helped me be more deliberate and thoughtful as you had to define everything up front.


> red flag is a bad description, because he ended up being self-reflective and looking deeper

No, red flag is fair since it's just a warning sign. Even if we take it as a mark on the guy, it's true that he ought to get outside the scripty bubble.


I built websites and wrote JavaScript for a long time before discovering generics by returning to school and being forced to build data structures from scratch in java. Other than that, there's no way I'd have ever come across them. I was just turned down from a senior position because someone had more years of React experience, so we're not exactly in the most sophisticated hierarchy here. Seniority should probably not depend on your exposure to technical language mechanics, especially those that weren't related to your area of expertise.


The author actively describes themselves as being "Anti-Typescript" and "hating" something they have no experience with. That's not skepticism.


Being skeptical shouldn't mean being ignorant. Being skeptical should mean Trying to understand the pros and cons and believing it's not worth it.


Or alternatively waiting it out a bit until it's more obvious what the pros and cons are (because others have tried it out in depth and shared their experience). Still a far cry from actively dismissing it.


Also more efficient. There's an endless, constant supply of new things not yet worth fully exploring.


The heuristic of "new JS tech is just needless complexity/over-engineering" is not a bad one to have in the JS ecosystem imo :)


Typescript is hardly "new", it's fairly widely accepted now. It might be worth thinking "why do all these people enjoy using Typescript?".

or idk just say that no, its the kids that are wrong.


I myself am quite fond of it actually! I was initially suspicious of Node at first and of TS as well, but like the author, I eventually gave it a try and liked it a lot. (Probably after many of the pain points had been worked out!)


I mean, Coffeescript was fairly widely used at its peak, and now it's all but dead.

Front-end fads are fickle. At least TypeScript has Microsoft backing it so they'll likely continue to support even if the rest of the webdev world moves on to the next shiny object.


I also have fond memories of painstakingly converting hundreds of coffeescript files back to JS. There's something to be said for using the native language.


In my private projects I always write in JavaScript and provide static typing using JSDoc comments (which typescript can check). Then I run the type checker with `--noEmit`. I have yet to run into a problem with this approach.


Browser support and consistency got a lot better.

JavaScript was a minefield of compatibility problems. Many intentional, cough: Microsoft.

Jquery was awesome because it dealt with most of that


JQuery dealt with DOM and browser stuff. Coffeescript dealt with syntactic language stuff. I can't think of a case where Coffeescript helps with the same thing JQuery does, although it may exist.


Yeah as best I can tell, Coffeescript was a thing because Ruby was very popular at the time, and some Ruby devs had to write JS but they wanted to write Ruby.


I was never a fan of the Rubyisms in Coffeescript. But it's sad nothing else ever implemented the YAMLisms.

Typing up constants in Babel JS is so much uglier than it needs to be.

But Coffeescript also introduced things like arrow functions that bind `this` to JS. Transpiling to ES5 allowed JS to evolve.


I think everyone except JS devs wishes they could write something other than JS for the browser.

Maybe eventually with WebAssembly...


That was definitely the case before ES2015. I think many of the non-JS devs that still hugely wish they could write something other than JS for the browser haven't kept up with ES2015+ nor Typescript. ES2015 is a much improved language and vanilla JS isn't painful anymore, especially with type="module" support now green enough in caniuse statistics that we can finally kill AMD and CommonJS for good in greenfield vanilla JS projects. The sky is quite sunny and ES2015+ is a better language than a lot of non-JS devs think JS is.

It will still be a while before all the brownfields in the larger ecosystem get cleaned up (if some of them ever do), but that's no longer a language problem, that's a a long tail ecosystem problem.


Yup. I don't find myself using classes much, but some of the other new features remove the vast number of issues you tend to face.

Is scoping an issue for you? Just use arrow functions!

Is callback nesting an issue for you? Just use `async/await`!

I love it so much.


I use classes a fair amount, but there's still some weird stuff in the language I'd take out if I could.

Sparse arrays, all object keys are strings (or symbols), crazy coercion rules, the existence of `null`, weird float vs int rules.


You can use `Map` instead of object which allows keys of any type, or typecheck your objects with `Record<K, V>` and let typescript warn you about any weirdness. Typescript can also warn you if you do some weird implicit coercion. You can typeguard against `null` (although I admit it is annoying, I just want to use an optional†). And if you really want to use integer types there is always `BigInt`.

---

†: I haven’t checked, but I bet there are some libraries out there that provide proper optionals using Proxy.


I use BigInt often, but you can't (for example) do most substring operations with it, even though floating point indexes make no sense.

Map goes part of the way to what I want. But I really want to control which objects are considered equivalent keys, rather than being limited to reference equality.


There's a Stage 2 proposal before TC-39 to add immutable Record and Tuple types [1] which would be structurally compared and perfect for complex Map keys.

It's also easy enough to find or write quick simple Map wrappers that use a hash function on an object as keys when provided (either piggy-backing on the existing Object.prototype.valueOf, which always exists on every object and easily falls back to the reference-based current behavior, and expecting classes to have custom overrides for that, or using a Symbol named function of their own to avoid polluting own-property-keys/name clashes with other libraries).

[1] https://github.com/tc39/proposal-record-tuple


Scala.js actually works really well. Frontend people aren't very aware of it, but if you're a backend dev who just needs to write a bit of code that has to run in the browser then I highly recommend it.


Even as an engineer happiest in Scala almost forced to write Typescript, I'll be the first to admit that the Scala.js library is still a bit lacking in comparison for real world productivity.


I had exactly the opposite experience. I kept trying to make Typescript work and it just wouldn't, eventually resorted to Scala.js and found (to my shock) that everything just worked and there were far less random rough edges.


That’s great :) Scala.js has such potential. I hope that my next opportunity to try it out (versus TypeScript) will be a similar experience to yours!


CoffeeScript served a purpose, and was not a fad. It got deprecated by an ECMAScript that adapted most of the good parts.

TypeScript brought something good for the JS ecosystem (although Flow did it too, in a different way) and it doesn't look like anything will be able to replace it at what it does anytime soon.


I am really hoping TC-39 starts considering optional static types (similar to python), using a simpler syntax then TypeScript (e.g. no enums). However I don’t have high hopes they will any time soon.


Coffeescript was a good thing when we only had ES5. In fact many of the things it championed made it into ES6 and beyond. I think with TypeScript it isn't just a shiny thing. If it does substantially change I believe it will be to break the forced compat with JS. As WebAssembly gets more adopted it will be possible to not have JS targets, and thus remove a lot of the weird JS things that have been kept for compatibility. Typescript has the gravity to continue.


I don't think I've ever heard of any in-production, large apps in Coffeescript, even from when it was at its peak. I know of a handful of companies that tried it and even enjoyed it quite a bit but none of it was for mass consumption.

Typescript, meanwhile, is used for hugely popular apps, is used by very large companies, has Microsoft's full backing, etc.

The two are not comparable.

Edit: Clearly I'm misremembering its popularity.


A significant portion of Airbnb was written in Coffeescript, including most of the complex app-like stuff used by hosts to manage listings and calendars.

We ported off of Coffeescript when ES6 and Babel came out, and you could start writing `class` and using `() => {...}` function expressions with lexical `this` scoping.

Coffeescript lost because it stood still next to the ecosystem and next to the new Ecmascript language standards, which obliviated its advantages. The only advantage Coffeescript had over ES6 was “some of your code is already written in it”.

Once Ecmascript formalizes a type system, we’ll see the same process happen with Typescript. But, I think it will be many years before that sort of feature is standardized. In the mean time, I’m happy to use Typescript today.


At one time, Dropbox and Github were all-in on Coffeescript e.g. https://web.archive.org/web/20130815075924/https://github.co...


Wasn’t CoffeeScript the preferred way to write JS in Ruby on Rails for years?


I think the Rails resource generators still default to creating Coffeescript files. I could be wrong though — I switch between Rails 4,5 and 6 projects right now. I’ve been on over a dozen Rails projects at different companies and only ever worked one project that used Coffeescript in production, and that was an app built pre-2010.


HAML and coffeescript.


I miss the elegance of Haml. Moving from an indented syntax for DOM literals to the likes of JSX felt like a step backwards.


Maybe for you, but that is not a popular opinion. JSX's rigor is a breath of fresh air in a world that constantly generates low quality html due to loose constraints. HAML had those same problems.

JSX is kind of xml done "right". Differences between children and attributes in xml is very hard to grasp, but JSX has a much better defined structure to it and is super well suited to generate html because of that.


This sounds like an orthogonal point. (I agree with it, so it feels odd to see it presented as a rebuttal.) Surely an indented syntax could have rigor if we wanted it to?


Sure, if we wanted it to, but HAML wasn't that.


Yes.


PagerDuty’s front end was 100% coffeescript until at least 2016


Square's entire merchant dashboard was in CoffeeScript. Half a million lines of code.

Took over a year to convert to ES6.


All the kids enjoyed using Javascript too. Language popularity is a bit of a random walk.


Typescript is not accepted. How AngularJS stuck on 1.* is the best proof, and an illustration for the problem. Pretty serious people are working in Angular community, it's immensely popular in the enterprise webapp space, so I will not take the "Ah, it's just amateurs who are stuck there."

It adds to countless attempts of other transpiled *scripts to extend Javascript.

They, and Coffeescript in particular, are good historical references to what will happen to TS in a few years.


About 95% of React components I see in the wild are in TypeScript. The most rapidly growing JS backend framework (Nest) is in TS. Deno, the evolution of Node, is based on TS. Pretty much everything in the JavaScript OSS world has TS options or is based on TS.

I doubt Coffeescript ever saw this scale of adoption.


We only use TypeScript on frameworks that make it a requirement, the language is starting to look like Haskell.

As much as I like Anders work, it is impossible to understand modern TypeScript without looking into tsconfig.json before looking into source code.


I don't understand what the tsconfig has to do with understanding the source? Maybe when using different path resolving or different tsconfigs to compile test files vs. production files?

Many toolings make it so you don't even need to worry about the tsconfig anymore (though in reality it is very helpful to understand it).


To avoid breaking existing source bases, many features or corrections across the language versions are opt-in, so in some projects it looks like GHC feature pragmas.


This does not align with my experience of writing Typescript at multiple companies of varying sizes and open source projects.


Lucky you for not having devs that would rather be using Haskell Lens and stuff like that.


I wrote AngularJS 1.x in TypeScript in an enterprise application. Being "stuck there" ("there" meaning pure JS for Angular 1.x) is a choice.


I took over a legacy AngularJS 1.x MEAN app early last year. One of the first things I did was to convert it from using Gulp to building the client with Create-React-App's build tooling:

https://blog.isquaredsoftware.com/2020/03/codebase-conversio...

That unlocked the ability to add React and TypeScript code embedded directly in the existing AngularJS UI, using the `react2angular` library, as a short-term migration approach. I was also able to migrate some of our existing AngularJS controllers and client logic to TS to get a bit more safety.

Since then, I've set up a new Next.js subproject that sits behind the existing Express app server, and was able to show content from Next by inserting iframes into the AngularJS templates and proxying those URLs from the Express app to the Next app. That's let us build new features from scratch inside of the Next codebase while showing them seamlessly in the AngularJS UI, giving us a long-term migration path.


I'll second that. We used AngularJS 1.x with TypeScript in an enterprise application.


I don't recall most major projects shipping with support for Coffeescript. Looking at my projects, the amount of "@types/*" I have are pretty small compared to a year or two ago because most projects ship types directly in their package now. Personally, I think it's here to stay.


I'd really like to hear what alternatives you have in mind for code in the JavaScript family that needs to have types. At my workplace, types are an important part of our workflow.

We've been using Flow as a type checker but are converting our code to TypeScript for the tooling, ecosystem, support, and hopefully improved performance.

TS has been running as a project for quite a while and a whole lot of folks have a stake in it. I think it's a pretty good bet.

Additionally, I was there when Angular 2 was announced, and the community had no idea what to do or when it was coming out and didn't know whether to dig their heels in and stay on 1 or what the migration path to 2 would look like. I think that's a slightly different story given the context.


> Coffeescript in particular, are good historical references to what will happen to TS in a few years.

The thing is that many good ideas of Coffee ended up being integrated in newer versions of JS, so of course the need for it decreased; one could argue that Coffee's legacy lives in ES201x.

But there are no types in JS, and none planned.


Yeah, it would be great if TC39 made type hints syntactically valid but semantically ignored (ala Python's PEPs to that effect) so that type erasure was no longer needed as a "build step", but so far TC39 is still hugely aware of the controversies surrounding ES4 (the "lost" version of JS) and still very hesitant to do anything type related in JS.


Looking at GitHub statistics, I would dare say TypeScript is pretty accepted: https://madnight.github.io/githut/#/pull_requests/2020/4

Out of all pull requests on GitHub in Q4/2020, 18.8% were JavaScript and 6.7% were TypeScript.

For reference CoffeeScript was at 0.25%. At its peak in 2014 it was at around 1.5%, when plain JavaScript was at over 20%.


That's my personal heuristic and why I continue to reject TS just like I avoided coffee script, flow, clojurescript, and so on.

But this article reads like "Developer who only used dynamic typing learns about static types." You could sub in any two such languages and get the same article.


One of the things you listed is not like the others. Why didn't you give Clojurescript a chance. It's like being in Hell and then someone brings you infinite amounts of cold fiji water. Hell becomes more bearable ;)


Clojurescript is the worst offender on that list from the point of view of "needlessly complicated." I can't imagine a dependency I want less than the Google Closure tools. I swear Closure is probably the only tool with fewer devs who understand it than autoconf.

I'm not critiquing any of those languages, in a perfect world any of them in the browser would have been preferable to Javascript. The issue is the tower of dependancies we are building, and you have to stop somewhere.


With advanced optimisiation turned on, the Clojurescript compiler will not include any of the Closure code that you do not use. But my point was about language superiority. For me it's obvious why Clojurescript wins the client side.


My issues is not the runtime dependency but the development dependancy. As the production apps I am responsible for keep getting older and older my opinions on ruthlessly cutting decencies get stronger and stronger.

Somewhere there's probably an optimal expected lifespan of a program where the line between preferring a better language and fewer development dependencies is crossed, but I'm also starting to learn that software stays around years longer than I ever anticipated.


Heuristics shouldn‘t really be a factor when you are a senior. Make a decision based on your competence and experience.


Agreed. A senior engineer should know when they don't understand something and keep an open mind about it rather than rejecting it outright.

If this article started with legitimate reasons for not wanting to adopt TS it would be different. "It is hard for people to learn" is actually a legit reason but "I don't understand it" is probably not!

That doesn't imply all new things are good or that senior engineers need to understand all new things either. I think there is some confusion about this.

Skepticism !== reject everything without grokking.


Senior probably means they've been doing JS for decades before TS was invented. They got along just fine without it for so many years, why rock the boat now? Or maybe it is more of a Senior person has a ton of work to do and not enough time to do it in so there isn't time left to learn a whole new way of writing JS. Or maybe many of the errors TS is meant to catch, the Senior developer has already learned over the decades not to do that bad thing, so they don't see the need to adopt TS. Or maybe they are just jaded and tired of learning new things.


I've been programming JS for 13 years (professionally, and some more as a hobby) and I'm pretty aware of its warts. And as a firm believer of TDD, most of my code is pretty well tested.

Unit tests have similar advantages to types: they catch errors early and let you refactor your code with confidence.

But unit tests go even further, because they test the _correctness_ of the returned value, not just its type.

And a massive turnoff for me is that the types are compile-time only.

So you see, if your code is tested, and the types are just partial static checks; I feel like it's just not worth it.

I enjoy using types in other languages, for example it feels nice to add type hinting to old PHP codebases. But in PHP, types are much simpler (less work) and more effective.

If they added optional run-time instrumentation like "spec" in Clojure, I would definitely use TS. But for now, I'm out.


You should be testing regardless of the strength of your type system.

But testing with a weak type system isn't going to give you anywhere near the guarantees you'd get from a well-designed type system in addition to testing: https://kevinmahoney.co.uk/articles/tests-vs-types/


I cannot wait to be the type of developer who just never makes typos.


Your IDE should be catching any typos. But it's not about typos, it's about understanding the quirky nature of JS and knowing what things not to do. For instance, an inexperienced developer might try to use .sort() to sort an array of numbers. It wouldn't even occur to an experienced developer to try that since they know from vast past experience that it won't work (or, at least, won't do what the inexperience developer is thinking it might do).


Does does my IDE know what functions should be called without types?


> Senior probably means they've been doing JS for decades before TS was invented.

JS has only been around for 25 years. I’m a “Senior person” and I’ve been seriously working with JS for less than 5 years.


Well, I'm Senior too and I've been working with JS for 23-24 years. So I guess I'm projecting my own experience.


Why not use something if you have an added benefit? It‘s like writing code in „ed“ just because it worked for decades


I find your interpretation and subsequent extrapolation on his qualification as senior unfair. He clearly tried TS and was frustrated by his initial experience, because there were certain things he had a hard time understanding or justifying. There's no opportunity for broader self development here. I try stuff out and I scratch my head, should I risk sticking with it or should I move on. It's a gamble. Others have made the alternative bet with a different tech du jour and lost. So your results may vary.


As a "senior" I'm still not sold. Running across bugs in the type checking that blocked us for a while (trying to avoid Broken Windows to boot) and the fact our development times skyrocketed (including on personal projects) or that the answer to poor tooling was "just use VSCode" is not something that really screams "developer friendly".


Sure, like all systems, there are overhead costs involved. But with something like a typed system, the overhead costs are minimal compared to the benefits you reap from them.

One of the projects I worked on during my transition to typescript was to convert an existing project into it. Sure there was a lot of head banging against walls at some point to get the types to work out, but during that process I finally really understood how everything fit together and gained a sense of assurance that I could use a return of a function with complete confidence. Developing on that project afterwards was also a breeze, moving faster and more confidently knowing that the object types were set, and that guardrails were in place to prevent myself from shooting my own foot.

It's a new system to work within the guidelines of, but guardrails are there for a reason, to prevent you from falling off a cliff.


The problem is, Javascript was never meant to be typed. It was never meant for what we use it for, even. When you start adding guard-rails to a language that already has guard-rails, what are you left with?

We spent more time screwing around with our Typescript types, getting the compiler to be happy, working around bugs with type assertions, etc. than we did focusing on the app logic at some points.

This kind of stuff, to compare, never really happens with C++. The type system is simple enough (compared to TS) that you can pretty confidently fix type errors quickly. I don't like Rust, but I know that the same occurs with Rust's type errors, too. Why is TS so difficult?

Because Microsoft created a type system that is so complex it can represent (almost) any type in a dynamically typed language. It's impressive, but not at all practical.


You are either going to catch the bugs in the type checker or you are going to have to write unit tests to catch them.

For me, typed python saves me a bunch of time.


Typed python takes ages to validate, and Python is much slower to run than Node.js, even with hacks like uvloop.

I've barked up that tree so many times, I don't think I'll ever go back to Python for that stuff in the future.


I think that he is presenting his prior attitude towards typescript a certain way for dramatic effect / so that it was easier to write a blog post about it. In reality he probably was not as skeptical as he sounds here -- otherwise we wouldn't be reading an article by him about how great typescript is.


I’d consider myself senior. I’ve been using Javascript since it was beta. I like Javascript. I don’t mind TypeScript. I mean, it’s nice and all but it doesn’t strike me as the be-all that others make it out to be. Maybe I just don’t use it for the types of project for which it was designed.

It’s like I’m a metal worker and I get along fine with a ball peen hammer. You come along and give me your claw hammer with great excitement. Sure, it can mostly do the same job, but my ball peen hammer is what I’m used to so I’m sticking with it.


I understand the sentiment, but a better comparison would be if your tool of choice had to be shared between everyone on your team.


Would that imply that the GP needs to reconsider their willingness to use TypeScript, or is it just a friendly reminder that there is utility in finding teams with shared values?


Senior does not mean "all around great zen person". It means an experienced person.

Seniors occasionally rejecting this or that, seniors occasionally blindly accepting this or that are both completely normal in majority of seniors.


Senior here. I was afraid if typescript will follow C# or Java's type checking. Both are too strict, verbose and inflexible.

I was afraid to introduce complex generic types because it isn't easily represented in typescript, or to change a struct from "person" to "employee" will need to map each properties individually.

Thankfully that wasn't the case.


Agreed, though at least there's one less developer writing about the "TypeScript Tax".


I am a TypeScript fan but I do acknowledge the existence of the tax. TS is another cog in the machine that does useful work but can sometimes confusingly interact with other cogs (e.g. miles long unreadable TS errors coming out of React). Using or not using TS is not a trivial decision to me and should be made with consideration to the complexity of your stack.


Can relate about illegible React stack traces in production builds. One of the reasons in my case was Create-React-App obfuscating ES6 class names, which is just insane! Just why???! Why throw all code structure away just to save a couple KBs. The worst part is CRA folks acting like dictators when asked to provide an option to toggle that: "Why in heavens earth would you need that?". "You can fork our 30K+ line repo [just to toggle minification] if you want".

Sorry for the off topic rant!

P.S: Yes I know source maps exist. They suck/aren't reliable.


You could also use customize-cra and skip on minifications in about 10 lines of code


I don't believe whether or not using TS has to do with the rest of your stack, but more about data consistency and the like.

I for one am building a large CRUD application with dozens of models spanning hundreds of fields, and Typescript is helping me (though not a panacea) keeping things correct.

I'm comparing it to a project I did years ago, first Backbone, then Angular, but both before 'typesave JS' was a thing, and that one relied heavily on reading and comparing keys and a deep knowledge of the domain.

But nearly ten years later, I don't have the mental capacity for that anymore and I need the crutches that typed languages offer me. By crutches I mean securities, safeguards and IDE assistance.

It makes sense for anything nontrivial IMO. Types allow you to be able to free up mental space. You can trust the type checker instead of having to rely on your own abilities.


I can't speak for the author, but I can speak from a similar path. Speaking for myself, I was self taught, and to even have a toehold in any kind of career I had to learn to prioritize advancement. Not having an educational or theoretical background, that meant evaluating "what seems most effective right now". I was late to adopt TDD, late to static types, late to FP, late to a zillion things... because I was prioritizing not being sent back to broke/poverty life. Once I had enough air to breathe I realized all of these things help serve me staying out of that misery, but the urgency of learning in the field doesn't always give room for that analysis.


I think moment when I really could call myself "senior developer" came when I realized annoying things I was struggling with are not stupid, it is just that I don't understand them very well.


My senior moment came when we were talking about graphics and I mentioned some various things and CGA. My coworkers let me ramble a bit and then one politely asked what CGA was.


Yes, type checking do not require a new language.


For me, I can handle the lack of static typing when I'm doing small scripts, like if it's going to be 100 lines or so of Python (my go-to language if I need to test some math out in a sandbox or do some file manipulation on my system). I might actually be a little faster in writing those scripts because of the lack of typing.

Once it starts getting any bigger than that, though, static typing really catches and points out a lot of problems before I even launch the program, that I'd otherwise be spending time debugging and looking for anyway, most likely.

I also think static typing has the benefit of enforced self-documentation a bit, so other developers know just by checking the type what sort of data they should expect to see in there, and not trying to give it garbage to begin with. Granted good variable naming and proper documentation would alleviate that, but that's never been fully consistent at any organization I've ever worked for.

And considering I mostly work with relational SQL databases, there's no escaping typing on the database end for that, so I might as well have models that map to the typing of what's in the database so I don't have to keep checking the database tables to make sure I'm giving it good data.


Naming is incredibly hard, though. And refactoring is hard.

It's a pain in the neck when something starts out as bla_list or whatever and you discover that after half a decade of changes bla_list isn't actually a list anymore, it's a dictionary, and that it doesn't only hold Bla these days, it can also contain Foo or Bar. This type of stuff is immediately obvious with modern static typing.


I agree, naming can be incredibly hard. I periodically spend a long time trying to decide the best name for variables, and at times whatever I come up with isn't satisfactory to me even then (and I usually try to explain it better in a comment at its declaration).

I don't always change the names if their use drifts a bit either because I know the other developers might be used to the code where it's named something else and it might confuse them, and/or I have to rename it in a bunch of places that might make a merge particularly messy, especially if I'm working in the same place that I think another dev might be working on at the same time (it's happened more often than you'd expect actually, I've had to do some particularly gnarly merges at times).


This feels more like developers learning that any variation on Hungarian notation is a bad idea.


This feels less like a case of Hungarian Notation being a bad idea and more like a case where developers are making irresponsible updates to their code. If a variable/function/class/whatever is being updated, the naming should be updated as well, if appropriate.

Blaming the original author for the actions of the maintainer is not fair.


I'd still blame the individual developer for poor naming. Naming a variable something like int_list is terrible in that it's both very specific and semantically meaningless. Either choose a semantic name like grades or part_numbers, or take a hint from ML convention and use semantically void names like "xs".


Sure, but is there anything stopping the person updating from revising the name? The original quality of the name is not relevant to my point, which is that anyone changing the code but leaving poor names behind is complicit in the debt.


You have to account for developers learning, for any code base, though. Let alone for third party dependencies :-)


I guess static first is a chore because at that point you have no idea what invariant or structure is required for the task. After prototyping you know where to tighten the bolts.


There is why TypeScript IS so great.

In the early days of a new app or feature, you have no idea what the correct data/type shapes are.

In TypeScript you can define the types and then easily do major refactors even if you have 1000's of lines already written.

It becomes so tedious to do the same refactoring in JavaScript.

TypeScript makes it trivial to change an object or function signature when developing new code (or old code).

Refactors that take 3 minutes in TypeScript take 3 days in JavaScript and you better hope you catch all the uses.

The refactor ability that TypeScript gives you makes it so much easier to change data types and function signatures dozens of times until you get things right.


> you have no idea what invariant or structure is required for the task

I often write the program in TypeScript types/interfaces first because it forces me to think about the data flow both in and out. In my opinion, data, not code, is the most important thing about a program.


that way of working was my only pleasurable experience in eclipse/java

start with interfaces and let the live type checker tell you where your incoherences are. Very very smooth way to work.


Sort of but at the same time being forced to think about those things also helps get a handle on exactly those parts of the program. Remember you still need to think about them in a dynamically typed language but it's obfuscated because they're implicit.


> you have no idea what invariant or structure is required for the task

In my experience, in general, if you don't already have an idea, you should probably be spending the up-front time thinking about it. If we're talking React/Redux, then carefully thinking through both data representation and what goes into components' properties/states helps a lot for designing a clean and understandable structure.


There are some languages that give you a bit of both worlds, like F#.


hey, the ml family is only 40+ years old, maybe in 50 years they'll be mainstream


This! My favourite thing about working with F# is the tiny delta between prototype script and production MVP.


Designing my types first is precisely how I want to begin prototyping.


> I also think static typing has the benefit of enforced self-documentation a bit, so other developers know just by checking the type what sort of data they should expect to see in there, and not trying to give it garbage to begin with. Granted good variable naming and proper documentation would alleviate that, but that's never been fully consistent at any organization I've ever worked for.

I don’t think naming is fully alleviated by static typing; however, on the other hand, static typing allows IDEs to offer better refactoring capabilities, since they can presumably build such functionality on top of the compiler’s structured syntax tree representations.

As an example, lately I fairly frequently find myself using VS Code capabilities to rename TS identifiers as my code evolves. It always handles correctly the scope and everything, I’m sure it’d be more error-prone with plain JS.

Agreed about statically typed code being more self-documenting in general. It’s a bit of a double-edged sword in that it may give an illusion that your project is easier to understand than it actually is, but it usefully shifts the focus of documentation from minute details of code itself to subject domain specifics and how you represent them in your architecture.


Seems like an easy cutoff is when you add a build step as opposed to just including your script on the page. If you need to use Webpack for a project, you might as well add TypeScript as well.


SQL is not typed, it is just text sent over a network or whatever and then parsed...


The schema and functions are typed.


I use type annotations in Python no matter what. It really helps skim the code faster and mentally understand what values I am expecting. Its very useful to know which var is a List[dict] and so on.

I don't like TS because javascript is just a silly language to do anything serious with (besides front end), and its so stringent it takes forever to write quickly.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: