Hacker News new | past | comments | ask | show | jobs | submit login
Every new web app at PayPal starts with TypeScript (medium.com/paypal-engineering)
117 points by davidgomes on Jan 21, 2019 | hide | past | favorite | 69 comments



Here's my strongest argument in favor of type safety: if you're building a project that is intended to have a long life and be seen by many people, type safety may be a hassle for you but it'll be a blessing for the hundreds of people who will have to eventually figure out your code.


The real truth though is type safety isn't a hassle. If your framework/libraries are already typed, then you will actually save a huge amount of effort. When you're working on your own code then you already know the types of the parameters; it takes only a moment to type them out. And then from that point forward, the mental effort is decreased because it's one less thing you have to think about in the code.

Type inference solves all the issues where entering type information was redundant and stupid. I will admit that old-school Java is maddening to work with for that reason but those days are long past now.


Not only is TypeScript's typing system less verbose, but it's smarter than old school (Java-esque) type systems. I just released a new version of Autumn[1] this morning that uses TypeScript's union types and type literals, and has this built-in: `type ModString = "command" | "control" | "option" | "shift"` so that now, even though you're still passing strings to Hotkey.activate, the IDE will actually warn you if you pass a typo like "comman". Not only that, but if you press Control-Space (same as in VS Code), it will actually auto-complete valid options for you. TypeScript is full of little goodies like this that are IDE-friendly, which is why I chose it for Autumn instead of plain JavaScript or Lua.

[1] the best macOS window manager: https://sephware.com/autumn/


I'm primarily a C# guy, so I'm no stranger to static typing - TypeScript's type system is a real joy to work with.

Between C#, F# and TypeScript, the three seem to be borrowing more and more from each other as time goes by (e.g. default interfaces and nullable reference types are coming in C# 8). It almost feels like they'll all converge at some point!


C# and Typescript are both co-developed by Anders Hejlsberg, so no wonder.


Why it make it a string enum then?

You can do that in any typed language too.


My argument is that if you value unit tests, why not get a whole slew of them for free from the compiler?


My team has recently focused on adding JSDoc to most of our codebase and I've been thinking, JSDoc provides essentially all the benefits (and more) of typescript from a maintainability aspect and contains none of the headaches (outdated definitely typed definitions, fighting with types...). As long as you use something to validate the JSDoc comments (like the JSDoc eslint plugin) they are extremely helpful in ways very similar to typescript. Language Servers like that in VSCode (tsserver) will inherit types from JSDoc comments and provide useful annotations with both the types and descriptions. They can even be used to show code examples or statically generated into webpages.

If your only argument is to use typescript for maintainability reasons doesn't using JSDoc extensively both solve and improve upon that goal?


I guess depends on exactly how you use JSDoc, but it sounds like you're talking about relatively informal documentation with some best-effort machine validation. My experience is that you don't get anywhere close to the confidence that you get with a real typechecker. Docs can be overlooked, docs can be misinterpreted, docs can get out of date, docs can be wrong by mistake. And, inevitably, if you have many people working with the same code over the course of years, these issues will be common. Having an actual typechecker avoids all of these problems, at least for documentation of data formats.

If you do mean annotating all types with the thoroughness that you'd annotate TypeScript code, then really you're just writing TypeScript in JS, and TypeScript is a much more concise language than JSDoc for that.


THANK YOU. I thought I was going crazy by being apparently the now 2nd person in the world who is perfectly happy with normal JavaScript plus slapping on JSDoc (mostly via custom vsc snippet) onto non trivial functions plugged into eslint. If I could make it fail lint when JSDoc doesn't exist I'd be perfectly fine with the maintainability of what I'm doing.


You can try something like facebook's flow which can be done as comments so no transpiler is needed.


Software should be designed for ease of reading, not ease of writing.

- John Ousterhout


It's funny to see the creator of Tcl (where nearly everything is a string, including lists, and blocks of code) quoted in a thread praising type safety.

Could it be that adding type safety isn't always an improvement to readability?


Note that it's possible to use both TSLint and ESLint in the same project, and that's what I've been doing for nontrivial projects. ESLint has a big community and a lot of nice rules, but there are a few things that ESLint can't (yet) do and that aren't implemented by TS itself:

* The TSLint no-unbound-method rule is really helpful for avoiding the React bug of passing `this.handleClick` at render time without it being a bound method. This is one of the "needs type info" rules that uses the type analysis from the TS compiler, and generally these sorts of rules are much more powerful than what you can normally get in ESLint.

* The TSLint ordered-imports rule with autofixing is a much nicer way to force import ordering than anything I've seen in ESLint. (ESLint sort-imports won't reorder your imports, for example.)

But as mentioned, the TS team has said that they want ESLint to be the future for TypeScript linting, so hopefully ESLint will get all of that soon enough.


We use both at Twitch, on a codebase approaching 7-digit lines of non-generated code. It’s worked out well for us.


My biggest grape with staticly typed languages like TypeScript is that many developers considers type safety a replacement for test - it is not. It is completely at best.


Heh, did you mean gripe?


I read his post as less of a critique of the linked article and more of a wine.


They say all bugs are type errors, but then I wonder how did they pass the type checker!? :P Some also think types replace documentation ...


Static typing doesn’t reduce bug density, this is no news, just a risk compensation principle at work.

But there’s another factor: static typing creates a nice puzzle for you to solve instead of solving the actual problem. You solve the puzzle and feel nice, you show the solution to management later and they feel nice to because it’s all neat and hierarchical. Then you write majority of the code that doesn’t neatly fit the puzzle’s constrains, then new feature requests/requirements come in and after a time the puzzle needs to be solved again. And so the wheel turns.

What people usually mean when they talk about static typing is a language to specify promises and requirements. To my knowledge that language has not yet been successfully reduced to mostly static and rigid annotations that are useful in dealing with changes to the software itself.


I've heard that argument before, but I've never seen that sort of behavior in practice. If anything, statically typed (or heavily annotated) codebases I've worked on have been much more amenable to change when it comes to adapting to "code that doesn’t neatly fit the puzzle’s constraints" as you say. The refactoring tooling and assurances provided by the type system tended to make people more willing to start rethinking their "puzzle" (type design) earlier in the process, rather than doubling down on a flawed model.

I've seen people do similarly great work in highly dynamic languages, too, so this isn't a "static > dynamic types" statement; just an anecdote in contrary to your claim.


The puzzle is not some inherent problem within the one you’re actually solving, it only arises because of limitations of any type system you choose to work with.


I don't think that's true. But even if I did, it doesn't address my point above that, in return for having to solve the "puzzle", programmers in more strongly-typed languages gain numerous other advantages.


> in return for having to solve the "puzzle", programmers in more strongly-typed languages gain numerous other advantages

advantages and disadvantages. and solution to the puzzle is almost always wrong or becomes outdated and requires major rethinkings often.


I found this true for Flow but not as much for TS


How so?


This thread is going to quickly devolve into the pro-type safety vs. the pro-flexibility camps. Look, if you looooove declaring types and somehow thinks this reduces bugs, great. If you just want to focus on the logic of your app and don't feel like managing the minutia of how the computer stores a number or string, great.

But if you want to declare one is fundamentally or empirically better, then you need to get a grip. We can all like different things, it's allowed.

The one core thing I'd like to stress, however, is that TS is not JS. If you use TypeScript, you are not using JavaScript. They are cousins, sure, or maybe uncle and niece, but they are not the same.


>Look, if you looooove declaring types and somehow thinks this reduces bugs, great.

I'm speechless. Do you believe type checking doesn't catch bugs? Because that's what it sounds like you're implying.

>But if you want to declare one is fundamentally or empirically better, then you need to get a grip. We can all like different things, it's allowed.

This is a ridiculous argument. People make such declarations because they believe them to be true. You're basically saying, "You're insane if you disagree with me that one is not fundamentally better than the other."

>The one core thing I'd like to stress, however, is that TS is not JS. If you use TypeScript, you are not using JavaScript. They are cousins, sure, or maybe uncle and niece, but they are not the same.

I don't see why this would stop anyone from using TypeScript. Why should we care?

(Also: When people say 'TypeScript is just JavaScript,' it's not because they're crazy. It is just saying something else. TypeScript is a strict superset of JavaScript that is compatible and compiles down trivially, which is in contrast to CoffeeScript for example, which was previously popular. Nobody was ever claiming that TypeScript triple equals JavaScript.)

...

You start off by implying that type-checking is ineffective ('[somehow think] this reduces bugs') then call for people to not engage in flame wars... what did you expect to happen?!


[flagged]


Okay, I don't think you're acting in good faith. Sorry, but thats not the response you get from someone not writing flamebait.


It's not flame bait at all, unless you aren't willing to accept different opinions, or have no real world experience. I believe exactly what I wrote. The discussion is unproductive and we can argue all day about the pros and cons. And TS isn't just JS, that's just marketing. Example: enum Color { red = 1, green = 2, blue = 4 } isn't even close to valid JS. And don't respond with caveats, as I don't care. I apparently know more than you do about it.


I already explained that in my post. I'll quote it verbatim:

>When people say 'TypeScript is just JavaScript,' it's not because they're crazy. It is just saying something else. TypeScript is a strict superset of JavaScript that is compatible and compiles down trivially, which is in contrast to CoffeeScript for example, which was previously popular. Nobody was ever claiming that TypeScript triple equals JavaScript.

Please drop the hostility. I'm not interested. If you don't want a reply you're free to quit replying yourself.


Actually, yeah, I'm being sort of a jerk. Sorry. Need some more coffee and a break from being online. ;-)


Good for you for recognising this though, it's important to be able to have reasonable discussions, to learn and grow.


TO BATTLE!

Reducing it to "pro type-safety vs pro-flexibility" doesn't tell the whole story. For me, it's "pro-consistency vs pro-inconsistency" or "pro-tooling-that-makes-sure-I-don't-screw-up-something-trivial vs pro-keeping-absolutely-everything-in-my-head-at-all-times." Of course, that's _also_ pretty superficial and unfair -- plenty of amazing work has and will be done without type safety -- but as a bonafide Kool-Aid-drinking TypeScript Cultist, I feel obligated to share that because it's made my life better.


There's a very simple rebuttal. Have this function:

  function greetPerson(name) { ... }
Call it in a bunch of places like this:

  greetPerson(user.name)
Now change the signature:

  function greetPerson(userId) { ... }
What code do you need to update to fix the breakage you now caused?

A dynamically typed language can't tell you without some serious static analysis, which to my knowledge doesn't exist. TypeScript can know this both when linting in your editor, and at compile time. Old signature:

  function greetPerson(name: string)
New signature:

  function greetPerson(userId: number)
Just write tests, some might say. But you've got your test right there: The type is the test for this particular problem. Unit tests should test behaviour, not types. (Since unit tests should cover failure cases, duck-typed languages arguably require that you test calling your functions with a wide variety of bad inputs.)

In practice, large programs will never have enough, or good enough, tests, because they have to be written separately from the code they're testing. Type systems allow us to describe our rules in the code.

Note that there are statically typed languages (OCaml and F# being notable examples) where the type inference is sufficiently good that you rarely need to write out the types of signatures, let alone variables or return values:

  let greetPerson name = ...

  greetPerson user.name
The fact that they can do this invalidates the usual "static typing require lots of unnecessary verbosity" argument, because it's not true.


I'd say the dynamic vs static should really be about team size/makeup and life expectancy of code base. Basically quickly building up things in a small team that might be around until a mature lifecycle (maybe startup-ish, prototype) vs big corp scenario where people working on code base will cycle through and the product is known to have a 5+ year life cycle from the start....


Yes, what you said is the 'generally accepted wisdom' and the cudgel with which the type-safety folk like to use to beat on the dynamic type folk, since pretty much all projects could potentially grow at some point, why not just start with type-safe first?

I could argue, but won't, that the accepted wisdom isn't correct, and large code base management is more about code discipline and reviews rather than whether your language requires types or not.


The title alone makes a good reason to further ignore typescript. If i should name a single major product that has the most horrible UI/UX it would be PayPal.


What does UI or UX have to do with language choice?


From what I can tell they use ASPX on their backend for the most part. So assuming that typescript is mostly used for frontend wasn't that far of a stretch.


Good UIs usually undergo rapid and extreme changes over very short periods of time. The choice of language could make it difficult or time consuming.


I've seen some great UIs that are cobbled together from bootstrap + several extensions with a bunch of monkey-patched CSS and other jQuery extensions... the code is a hodge-podge mess that I didn't enjoy working with, but the UI itself was quite pretty/useful.

I've seen the opposite as well. One does not beget the other. On my current project, I'm often doing a followup pass on the UI/UX for this project.


It doesn't in this case.


Sure it does. We often have designers jumping in and programming UI code themselves. Teaching them all about type systems would be very time consuming.


As consumers of a library? Quick, what kind of object can I use this function with?

function computeAge(birthday: Date): int;


I might have agreed once, but PayPal's UI/UX has been dramatically improving in the last year or so.


>> What took took me so long?

It took a while for all of Microsoft's marketing to kick in and for the mindless hypewagon to reach full speed.

I have decades of experience with Typed ECMAScript (first with ActionScript 3 from 2006 and then TypeScript). It's not worth it. Productivity will drop enormously and bug density will not change at all.


> It's not worth it. Productivity will drop enormously

How does TypeScript make your "productivity drop enormously"? It has type inference, union types, looks just like ES6, and the typing is fully optional. The learning curve is quick if you've ever done static typing before (and not that hard even if you haven't).

And you get the productivity boost of not dealing with a lot of the regular JavaScript BS (no more "spooky undefined at a distance" because somebody forgot a 3rd parameter 4 methods down the callstack), as well as the ability to safely and automatically refactor, and the ability to immediately understand the API of other people's code or libraries (as long as it's typed, and most popular libraries have type definitions now).

In my experience the productivity benefits more than make up for the time you spend managing your types.


>> How does TypeScript make your "productivity drop enormously

- Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up - Especially on large projects and especially if you're not used to having a build step during development.

- Sporadic source mapping issues/bugs which makes it hard to fix things (I had an issue with Mocha tests last week where it was always telling me that the issue was on line 1). I've worked with TypeScript on multiple projects across different companies but every single time, there has been source mapping or configuration issues of some kind.

- Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

- Third party libraries are difficult to integrate into my project's code due to conflicts in type names or structural philosophy (e.g. they leverage types to impose constraints which are inconsistent with my project requirements).

- Doesn't guarantee type safety at runtime; e.g. If parsing an object from JSON at runtime; you still need to do type validation explicitly. The 'unknown' type helps but it's not clear that this whole flow of validating unknown data and then casting to a known type adds any value over regular schema validation done in plain JavaScript.

- Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

- Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

- The 'rename symbol' feature supported by some IDEs is nice, but if a class or property is mentioned inside a string (e.g. in a test case definition) then it will not rename that; so I still have to do text search after doing a symbol rename and manually clean up.

- It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one. It often comes down to what constraints you want to impose on users; This adds a whole layer of unnecessary mental work which could have been better spent on thinking about logic and coming up with meaningful abstractions which don't require arbitrary constraints to be imposed.

- Setting up TypeScript is a pain.

- Adds a lot of dependencies and complexity. It's a miracle that TypeScript works at all given how much complexity it sweeps under the carpet. Have you looked at the output JavaScript? Try to compile something that uses async generators and see what the output looks like.


I feel conflicted because just a couple years ago most comments to typescript articles were like the one above. Now that people are finally coming around and seeing the huge benefits to adopting it, comments like the one above are becoming more rare. People are still hung up on typescript not being perfect. Well perfect is the enemy of the good, and the good typescript brings is immense. Working on front end code across a 40 person team used to be a nightmare.

Dynamic typing is great when you're learning to code because compiler errors/warnings are intimidating. Once you do know how to code the compiler actually becomes a useful assistant that increases productivity. Helping you avoid dumb mistakes and make refactoring much easier.


Can confirm most of these points, but still believe TypeScript is a net positive for productivity, when you consider things like refactoring tools (VS Code). And on top of that add increased safety, less bugs and improved code quality because if you encounter something problematic you will actually dare improve it, because things are much less likely to break.


Thanks for details. Here's my response to most of them (some of this is definitely anecdotal of course).

> - Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up.

I've not personally encountered any significant compiling overhead in comparison to a regular Babel ES6 transpile. Obviously depends on project size, but there are a lot of tweaks that you can do to speed it up. I've had good luck with ts-loader.

> - Sporadic source mapping issues/bugs which makes it hard to fix things (I had an issue with Mocha tests last week where it was always telling me that the issue was on line 1). I've worked with TypeScript on multiple projects across different companies but every single time, there has been source mapping or configuration issues of some kind.

Are you advocating ES6 instead of TypeScript? It seems like all modern JS hits a transpilation stage before it hits the browser these days, and I see the same source mapping issues whenever I use ES6/7 with Babel + Webpack.

> - Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

Fair point, although I haven't run into this much myself.

> - Third party libraries are difficult to integrate into my project's code due to conflicts in type names or structural philosophy (e.g. they leverage types to impose constraints which are inconsistent with my project requirements).

Not sure I follow, do you have an example?

> - Doesn't guarantee type safety at runtime; e.g. If parsing an object from JSON at runtime; you still need to do type validation explicitly. The 'unknown' type helps but it's not clear that this whole flow of validating unknown data and then casting to a known type adds any value over regular schema validation done in plain JavaScript.

I mostly agree with this, which is why my strategy is just to do regular JS style schema validation where necessary, and then cast the object, rather than relying on `unknown`.

> - Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

Not sure I fully follow. If your code compiles to the point where you can use the debugger, you should have been able to use a console.log as well, right?

> - Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

If you're writing code used by others, you need to be clear about what your API expects and allows anyway, so why not be explicit about it, in a way that the compiler can enforce? An intelligent person makes mistakes, so why not see if you can give the computer the ability to catch some of those for you? And TypeScript still gives an intelligent user the ability to supersede your type restrictions if they absolutely need to.

> - It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one. It often comes down to what constraints you want to impose on users; This adds a whole layer of unnecessary mental work which could have been better spent on thinking about logic only.

I don't think coming up with good interface names is more difficult than good class or method names. And I'd argue that thinking about the constraints you want to impose on users is important for developing maintainable code -- whether you're doing type checking or not. And ultimately those constraints still have to exist in some manner, but without type checking the "constraint" will be the code breaking in some undefined way. By doing so you save yourself and others the mental overhead of trying to figure out what types you're dealing with at any point in your code base, or what types you're expected to pass into any given function. The initial overhead of thinking about your types pays off quickly.

> - Setting up TypeScript is a pain.

Anecdotal, but I've never had much of a problem with it (for React users, I believe you can get it for free in create-react-app now). And it's a one time setup cost anyway.


> Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up - Especially on large projects.

But you can have decreased tests because you have to test for common typing issues. A lot of my PHP tests are type-checks.

> Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

I've had this happen with a very obscure library that was partially-typed by someone (god bless their soul) but it took me only a few minutes to manually make the changes to the definition.

> Doesn't guarantee type safety at runtime

That's not the purpose of the product though. It's like complaining you can't cook a turkey in the microwave; It's true, it would be a nice, but it certainly doesn't mean microwaves are bad -- they're just for a different purpose.

> Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

Constraints? I would call it documentation. I'm sure you're users would appreciate knowing what methods your class has and what the parameters are.

> Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

Tell TypeScript to always generate the JavaScript code even on type errors and then you don't have to let it slow you down.

> The 'rename symbol' feature supported by some IDEs is nice, but if a class or property is mentioned inside a string (e.g. in a test case definition) then it will not rename that; so I still have to do text search after doing a symbol rename and manually clean up.

I think it's a good reason to avoid storing identifiers in strings which is an anti-pattern in any language. Either way, you have this problem without TypeScript. Because it doesn't solve every problem that makes a poor excuse to keep it from solving some problems.

> It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one.

I agree totally! It's never been easier to refactor and rename than with a strongly typed language. Admittedly I haven't done too much work making these big changes in TypeScript but definitely have done it with C#/Java and compared to dynamic languages the speed you can make correct changes is amazing. You can see your mistakes as you type with good tooling.

> Setting up TypeScript is a pain.

I've setup a complete modern JavaScript tool setup and setting up TypeScript is by far the easiest part of that.

> Adds a lot of dependencies and complexity. It's a miracle that TypeScript works at all given how much complexity it sweeps under the carpet. Have you looked at the output JavaScript? Try to compile something that uses async generators and see what the output looks like.

That's what async generators do. They do the same thing in other languages (just look at the disassembly). It automates creating a state machine. I don't see why anyone would want to write a state machine themselves rather than let the compiler do it for you. It's actually difficult enough that most people wouldn't do it even though it's a great programming pattern.


>> I've setup a complete modern JavaScript tool setup and setting up TypeScript is by far the easiest part of that.

I see what you mean. Maybe that is the root of the problem and the reason for TypeScript's increasing popularity. The fact that the author of the article mentioned Flow also suggests that there is a similar effect at play in his case; devs get used to the build step and since they're already spending time building JS, they might as well start building TS.

I hate bundling during development so I'm not used to waiting around when debugging. Unfortunately, most modern front-end coding approaches depend on having a bundling step during development. I guess front end development is in a bad state right now. I tried VueJS a few months ago and I was shocked at how difficult it was to find information on how to use it without the bundling step. I was able to figure it out eventually and it turned out to be a very nice framework but the information necessary to get that ideal setup was just not there.


I'm not a fan of bundling/packing obsession either, but I've come to recognize its necessity, at least at present. If you want to use any external libraries in a reliable way, or don't want to serve massive, incompatible-with-some-browsers JS files, I just don't think there's currently a way around using some sort of bundler (or, alternatively, paying the cost in slowed-down development and/or stacks of compatibility-related annoyances based on the "modern"-ness of any code you write or import). For tiny projects you may not need one, but beyond that the convenience benefits are just too great.

Every time I've tried to avoid using a bundler in development, I've either regretted it (babel/webpack/whatnot has screwed something up in prod that I didn't catch in dev), or ended up shoving the important parts of a bundler into browser plugins that roughly execute the bits of the build phase I care about in the browser when the page loads.


I feel you. I've just starting a project from scratch using modern JS development stack including TypeScript. I've previously just done by JS without any tooling at all (besides an IDE). And I have used TypeScript stand-alone without the rest of JS bundling infrastructure.

I also used to do more dynamic back-end development (PHP) but a long time now my backend work has been C#.

The future of JavaScript, probably the future of web development in general, is with a compilation/build step. Having a fully dynamic uncompiled front-end and back-end code was probably just temporary blimp. The tooling, though, already understands your concerns and has plenty of features for editing and running without noticing the build step. I could configure the TS build environment to re-load scripts on edit and I don't even have to press refresh in the browser to see the effects.

It does all feel very heavily and complicated but sometimes I have to wonder if that's just me.


Thanks for taking the time to create this detailed and helpful answer. I appreciate your work.


> Slow debug cycle due to increased compile time. If using TDD, it takes longer to run tests. The delays adds up - Especially on large projects and especially if you're not used to having a build step during development.

It is a bit slower. There is tooling to mitigate this (filesystem watchers and such), and I've only found it to be a big stumbling block on relatively large TS projects, but you're not wrong. In almost all cases, large projects without some sort of build phase are probably pushing incompatible and/or slow code.

> Sporadic source mapping issues/bugs which makes it hard to fix things (I had an issue with Mocha tests last week where it was always telling me that the issue was on line 1). I've worked with TypeScript on multiple projects across different companies but every single time, there has been source mapping or configuration issues of some kind.

That's not TypeScript's fault, in my experience. It's usually because of a relatively byzantine build system that's in charge of generating sourcemaps. In fact, I've never seen sourcemap bugs that were directly caused by TS (i.e. due to Babel/Webpack misconfiguration). YMMV, of course.

> Type definitions from DefinitelyTyped are often out of date or have missing properties/methods. It means that I can't use the latest version of a library.

This is the criticism I agree with the most. Things are improving as people start developing in TS more and shipping typings with their projects as first-class citizens, but it has a long way to go (PDFJS, looking at you).

> Third party libraries are difficult to integrate into my project's code due to conflicts in type names or structural philosophy (e.g. they leverage types to impose constraints which are inconsistent with my project requirements).

Not unique to typescript at all. If you have a promise/async-based control flow and you integrate a library that is all about fire-and-forget with eventEmitter subscriptions, it's going to look weird to integrate. If a library you import uses a different naming scheme, or a very different pattern (e.g. heavily chained single-purpose methods vs. a more declarative style with big config objects), it's going to cause friction. In TS, most of the typing/naming friction I experience is caused by modules that would have caused friction in pure JS as well.

> Doesn't guarantee type safety at runtime; e.g. If parsing an object from JSON at runtime; you still need to do type validation explicitly. The 'unknown' type helps but it's not clear that this whole flow of validating unknown data and then casting to a known type adds any value over regular schema validation done in plain JavaScript.

"This toaster doesn't make me coffee! Before I got it, I couldn't make toast or coffee. Now I just can't make coffee. What a terrible toaster!"

> Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking about how to impose constraints on the user of the library/module instead of assuming that the user is an intelligent person who knows what they're doing.

That's probably the single biggest benefit of using a type system.

Many folks think the biggest benefit is the compiler rejecting code which violates type rules and thus prevents bugs. I respect that, but I think that's in the second spot after "type systems make you actually think about your data transformations beforehand". This feels annoying at first, and still feels annoying when organically growing/prototyping brand new stuff in an exploratory way. But man does it pay off in a hurry: once your project becomes just "small" instead of "tiny", you'll be glad you (were forced to have) thought about those structures as a whole rather than as problems came up.

> Compiler warnings make it hard to test code quickly using console.log(...); I'm more reliant on clunky debuggers which slows me down a lot and breaks my train of thought.

I'm not sure what you mean. If you mean "my code doesn't compile so I can't run it and printf debug", then see my response to your point above this one: while that may feel less superficially satisfying, it's saving you time and hassles in the short and medium (as opposed to immediate) term. If you mean "console.log causes the compiler to emit a warning or error", you can likely turn that off (e.g. no-console).

Regardless, I'm with you in the spirit that printf debugging should be easy and that you shouldn't be forced to use a debugger.

> The 'rename symbol' feature supported by some IDEs is nice, but if a class or property is mentioned inside a string (e.g. in a test case definition) then it will not rename that; so I still have to do text search after doing a symbol rename and manually clean up.

Sounds like an issue in the way you're writing test cases. This is just as much of a pain when refactoring highly dynamic pure JS. If something relies on stringy descriptions of objects/properties its interacting with, it's usually the last thing to be caught in a refactor and the first to produce bugs. Just say no to pointless metaprogramming.

> It takes a lot of time think of good names for interfaces and they are renamed often as project requirements evolve. It's not always clear whether similar concepts should be different types or merged into one. It often comes down to what constraints you want to impose on users; This adds a whole layer of unnecessary mental work which could have been better spent on thinking about logic and coming up with meaningful abstractions which don't require arbitrary constraints to be imposed.

This is the same as your above point, "Whenever I write any class/method, I have to spend a considerable amount of time and energy thinking". It's a different paradigm than the immediately-satisfying-feeling you get from writing little bits of code and seeing them immediately "work" for a given test case. It takes some getting used to if you like the feeling of frequent, steady, incremental progress. But after trying it for awhile, I bet you'll find that you've developed features faster and feel more confident that they'll behave correctly in unexpected situations. You also may find that, if you think about the typing beforehand, when it comes time to start "thinking about logic and coming up with meaningful abstractions" you'll find those things much easier to do if you don't have to think about e.g. nullability edge cases while you do. Personally, I find that it orders my thinking into a "How do I constrain and/or generalize what the behavior must be" phase and a "now define the behavior for this specific constrained type" phase, which is very useful--especially in heavily-generalized systems like form builders or otherwise user-customizable display editors.

> Setting up TypeScript is a pain.

Sure is. It's gotten a lot better, but has a ways to go yet.

> Adds a lot of dependencies and complexity. It's a miracle that TypeScript works at all given how much complexity it sweeps under the carpet. Have you looked at the output JavaScript? Try to compile something that uses async generators and see what the output looks like.

If your TS project is big enough that you're suffering from compile times as you mentioned above, you probably use (or should be using) a build step. I've never seen a JS polyfiller that doesn't create insane code when presented with things like async generators. I'm not sure how TypeScript is different. You can tell it to output non-polyfilled JS with the '--target' config, which defaults to ultra-backwards-compatible ES3. Come to think of it, that might be why you're seeing both crazy generated code and slow compile times: https://www.typescriptlang.org/docs/handbook/compiler-option...


My personal experience is that AS3 was a better experience over JS and Flex4 was a pleasure to work over the JS frameworks and CSS mess.


Overall AS3 with Flex felt great, and I used it for one of the funnest projects I've ever worked on (prototyping for a new GUI system).

The inbuilt widgets functionalities were great, with things like skinning functionality and the ability to place shaders on widgets right on your fingertip. States were easy to model. I think it took Javascript years to catch up, and while now some of the modern frameworks (React, Angular, Vue) might be ahead in lots of regards, they might still be behind in others.

Actionscript itself had a pretty weak type system compared to what Typescript can do now (or could do years ago). E.g. there were no generics, apart from the some kind of semimagical vector. So this one is the smaller loss.


I agree, my point was not that AS3 > TS , my point was that AS3 > JS still and AS3 is old and it had no improvements in years. The GUI part is still behind though, you still can't CSS the scrollbars and you need a JS library, you can't CSS the select options and you need a library to create a better dropdown, you have no built-in or a standard set of Widgets simlar to the DataGrid or AdvancedDataGrid, working on some old projects CSS drives me crazy


AS3 was better than TypeScript in several ways;

- It was interpreted natively (no build step). It was fast. AS3 was much faster than AS2.

- It was heavily targeted at games. Games have a lot of objects and those objects tend to have complex relationships with each other (I.e. more inheritance and more polymorphic compositions; where different objects can be passed to the same method to produce different effects).


If I have to continue doing any kind of front end work, I would be very okay with a native TypeScript runtime in the browser with support for modules. Add in the option for a flag to skip type-checking and we might have a win-win for fans of pure ES6/7/8.


I'm not sure that I agree... AS3 had typing that was very similar (originally part of ES4 spec).

I often feel that it can make some code that should be simple more complicated and sometimes reduces some flexibility in practice, or is harder to define. What research I can find indicates it's mostly a wash on time. You prevent a certain class of bugs, but at the same time you have the time to add typing.

In the end, I think it depends. If you're working on a large project with a lot of developers in differing areas, the appeal is growing on me. In the end, when working on code you don't trust with behaviors that are loosely defined, you get at least a little more confidence in refactoring things out.

I've worked with and without. I prefer without, but now am working on a project I wish I'd started with it. I still want to use it with babel as there are a few features I want to use that are not yet in the browser.


Part of me feels the same way. I've been through AS3, Coffeescript, Dart, and now the Typescript hypewagons.

I'm willing to give it a deep dive, but I'd rather see an optional flag in an upcoming ES version for types and other TS superset features.


Aside from type annotations, TS only has one superset feature (decorators). It's already behind a flag.


and namespaces and enums at least.


Namespaces are considered a deprecated artifact from TS < 1 and most projects suggest turning on lint errors for using them. Even if you do them, they are simple syntax sugar for an IIFE pattern that has been common in JS since forever.

Enums are simple syntax sugar for constants patterns you could write by hand easily.

Other than decorators and JSX-related stuff (also behind compiler flags), TS has been pretty strict about keeping only to Stage 3+ ES proposals since 1.x. Decorators got a strong push from Angular-based teams and JSX gets a lot of attention from React-based teams, so its also not like TS is adding stuff "just because", they are doing it for real world project engineering needs.


Thanks, I had forgotten about those.




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

Search: