What are other folks experiences? Has it helped or hindered?
What are other folks experiences? Has it helped or hindered?
CONS:
1. Contribute a couple of times to DefinitelyType repo, because I needed definitions that doesn't exist or modify existing ones with their updated versions ( this is really pain in the ass at this point, because you will most certainly end up using definitions that either doesn't match your version number or are poorly written ).
2. Report a couple of bugs to WebStorm 10 team ( I'm eagerly waiting for WS 11, which they say will improve the typescript support ).
3. Explain to my clients why I am using a beta version of a software for their precious product ( this is not a problem since today :) )
4. Sometimes the flexibility of typescript can slow you down a lot if you want to go deep with the proper typings and interface declarations. I actually spend a lot of time thinking how to organize my classes and interfaces now, instead of writing code.
PROS:
1. Code looks solid and professional ( CoffeeScript on the other - I was so much faster, but in the end I see not that easy readable code. )
2. Creating documentation is way easier ( using typedoc ). I never understood JSDocs as a pro and usually I spend lots of time on properly annotating, which is unneeded in TS.
3. There is no need to write `function(options) { if ( !options ) { throw new Error("Options required"); } }`. this becomes `function(options : Object) {}`. This removes a lot of boilerplate and really cleans many of those typesafety checks from your code.
4. I'm catching far more errors in the compilation phase than ever before ( see 3 ). I'm also not writing any typesafety tests for my modules ( I was so happy, when I realised that! ).
What I think is the best part though, and it helps when bringing new people in, is the crazy-good intellisense you can get in Javascript now.
Basically it makes averages developers much better, and skilled developers a bit better. Master level folks may just find some boilerplate generated code annoying, but for my definition of "Master" there aren't many of them around anyway (at least not where I work).
When I moved my team's JS code to typescript, I found myself way way faster with the improved intellisense.
I wrote most of the code originally and understood it well, but even for an experienced developer, solid intellisense saves you from having to look up so many things.
The module/class/types system tends to push you in certain direction for your overall design, compared to a more amorphous vanillaJS.
Even then, the language features don't replace coding rules and discipline. To pick one feature, protected and private members are little more than polite suggestions in typescript, and can be bypassed easily if that's culturally acceptable in your dev team, losing the benefit of well defined interfaces between chunks of code. If Typescript feels generally useless and even a hindrance to a team, it's very possible that team is working outside of the bounds Typescript is meant for. For example, I can certainly imagine a tight knit bunch of crazed coders writing fantastic JS code that really doesn't fit in a java-like development model. If that's the case, you'd probably want to think about why your team migrated to Typescript in the first place, and what you were hoping to gain from it.
The generated boilerplate complaint surprises me a bit. Typescript produces very little extra code, and has almost zero runtime overhead. There's an 5 liner __extends helper function, but that's about it. Most of the time, a line of TS maps to an essentially identical line of JS. I understand that's becoming less true with the fancier syntactic sugar of recent releases, but we're still in the same general ballpark. (and of course, the extra code melts away if you're able to target higher ES versions.)
The learning curve bit really depends on your team's background. Folks coming from many non-JS language will have been exposed to modules/namespaces, classes and types. They will be able to write reasonable code with typescript for a while before even realizing JS has this strange and intriguing prototype mechanism, although it can be a bit of a shock when the day comes, and an ancient JavaScript bearded one sits them down and gives them The Talk about what lurks in the basement.
The main con is that sometimes things are not very clear and you might end up spending time on something that typescript can't handle (eg a function that can return several types of objects, I had to put the return type of the function to any to have it compiled).
The pros:
- being able to refactor stuff easily with the compiler telling you
- catch typos easily (I remember watching Dan Abramov video at react europe and some of the errors he showed would be a compilation error in TS)
- if you maintain all your classes/object definitions in one file (except maybe stuff like state of a React component which doesn't need to be shared), you have all your types at one place and anyone can come in and have a clear view of the project: I had someone come help me on a previous project and it took him basically no time to get a grip on the project structure/models
- DefinitelyTyped so you can also type your calls to third party libraries and what they return
Make sure to only use ES6 imports (no internal modules) and it's pretty close to babel but with types.
Typescript 1.4 to the rescue with union types!
Though I would argue that if this is code you're writing yourself, a function that returns multiple types is bad design. Though given the prevalence of different types for different strings, the way they've typed things like addEventListener is interesting.
The other aspect is that if you're a C# shop it is so similar as to reduce the learning curve. Especially if you want to write OO front end code.
The good parts :
* The type system serves as a great safety net and prevents a whole class of bugs.
* Intellisense is far smarter than you would get from JavaScript (no more silly IDEs with both jQuery's .append() and DOM's .appendChild() in the same intellisense suggestion). This enables refactorings and intelligent assistance such as Find All References, which is much more brittle in plain JS.
* Classes are much more convenient and readable than old-school inheritance solutions. Those old solutions were also a huge problem for JS intellisense.
* AMD Modules paired with Require.js are much more centralized than "add these fifty script tags to the HTML document, in the right order". That's more due to AMD, but TypeScript adds some nice syntax sugar on top of that.
* Arrow functions. No more `var that = this` to keep callbacks working.
* Generics, function overloads, etc. - depends on the things you use in your code. If most of your viewmodel properties are Knockout Observables, generics are a life saver. If you're chaining Promises, again, generics can cover their return/param types. Function overloads come in handy if you have factories building objects based on string parameters (example: document.createElement() returns different classes based on the name passed in). And so on.
The bad parts :
* New language to learn. And it keeps evolving.
* Requires an additional build step. There's a large amount of small projects without any build process out there - integrating TS into such a project can be difficult and open a new can of worms related more to the build process than TS (e.g. "do you commit the generated JS and sourcemaps, or provision a build server to package them?"). Of course, if you're already using Grunt/Ant/Phing/whatever else, this is not a big problem. (You should be using a build process at least to aggregate your JS into one blob, if nothing else.)
* Definitions for third-party libraries. DefinitelyTyped helps a lot here, but there are still things that it doesn't cover, and it can be time-consuming to keep a definition file in sync with a library as the library updates.
* IDE support. After using PHPStorm/IntelliJ and Visual Studio Express/Community, Visual Studio wins hands down. IntelliJ's support was quite disappointing and glitchy, especially its lack of intellisense. Visual Studio Code, Community and Express are all free, but the latter two are quite bulky and running them alongside a different IDE can be slow.
* Debugging can be a bit challenging due to sourcemaps, depending on the target browser. I prefer to disable sourcemaps and debug the generated JS directly, but that requires some mental juggling and is not everyone's cup of tea.
A lot of the “new language” parts is ES6, stuff that will be becoming more commonly used soon and which there is value in. The parts that are actually TypeScript itself are very much more restricted and really are just bits around the type system.
To me, simply being able to break up methods into discrete testable modules, then composing those methods into either workflows or structured utilities, you don't need the cognitive overhead of strict typing nearly as much. Unfortunately, going that route takes discipline.
What typescript and es6 tends to bring is cleaner class syntax, which imho is a detriment to the use of JS in most cases. People tend to put things into classes that really don't need to be. You data structures can be plain objects instantiated as needed (generally via JSON passing), and most of your workflow logic can again be a module that is an object which returns a composite of discrete, or at least bound/wrapped functions that themselves are independent and testable.
One thing you should probably strive for in a green project where there is a lot of JS, and multiple developers is 100% test coverage for JS. If you are having serious issues with being able to test your code, odds are your structure needs to be cleaned up. With utilities like sinon and proxyquire you should be able to shim for testing anything a method needs to be exercised.
It's also worth noting that test coverage doesn't guarantee good code, it only ensures that you've looked at every piece of code a couple of times. It's that forced review/refactor for testing that gets you thinking in terms of usability. Filling out an existing software with unit tests without refactoring as you go, only gives you some protection against regressions.
I have totally lost track of where I was going... I guess it just comes down to that, for me, TS brings the limitations in terms of testing that exist in Java and .Net and force them on JS. JS is inherently more easily testable than many other languages.
In my mind though, the main benefit is types as documentation, both for devs & tool support. Via DefinitelyTyped it makes integrating new libraries simpler. It has made refactoring much more straight forward. I started a side project on the weekend where I wanted a chrome extension, and I made that a typescript and have absolutely no regrets. I've been doing lots of regular refactoring, and while the codebase is miniscule, it's a lot more mechanical to make changes (change the type, look for red squigglies) than really needing to think about where the changes are.
But I feel like our code is very much much more navigable than just straight JS. Being able to know the type of a thing and just jump to its definition makes it that much easier to read. I might have been scarred by my previous experiences trying to read large dynamically typed projects, but you can't just jump into most files and be able to figure out what is going on (particularly with classes).
We only have one typescript codebase, which we moved to from coffeescript, and that was a huge win, partly because of coffeescript, but also because the coffeescript codebase was a disaster and needed some rework. When I originally ported it, it was about 4k LoC in a single file, and now it is 11k across 93 files. My team wasn't entirely thrilled with typescript to start, but some of the features in 1.4 (union types, typedefs) made people happier. We have some very different coding styles, from my end where I want to type everything, to the any-soup we get in some parts.
So, I can't call it an unmitigated success, some of what the codebase needed was just some general structure, but 11k isn't exactly a huge project either, and it's structure is really not very complicated (most of it is completely independent modules).
So, after all that rambling, things I like:
- code navigability (particularly because anything you do a method call tends to be typed)
- code completion
- refactoring is simple
- catches straight forward bugs earlier, rather than me finding them when I test
So, despite it having types, the main benefit has not really less bugs, it's made my life interacting with the code simpler, and it has made bugs caught by the compiler easier to track down.
I think there was a real missed opportunity to have browser definitions split up by browser version so that you could more easily specify a target set and have it show you when you use something not supported though.