4
Oct

TypeScript Reloaded

Before we go any further, let’s be honest, The Matrix Reloaded really wasn’t such a bad movie. It wasn’t ok? Hey, I’m serious! It wasn’t!

Bah, whatever. Let’s jump right into it then.

Ugh! Are We Still Talking About TypeScript?

Well, I wrote this overall negative post a while back and turns out… we’re using TypeScript now. It would be pretty hypocritical not to come back to it and talk about what’s changed for us to like it again, right?

So what changed? Well, quite a lot, but let’s first revisit my main critiques of the language from that post before and see how they have been solved.

Typings

Typings is a bit like that. Exactly like that actually.

Typings is a bit like that. Exactly like that actually.

Thank the Lord, typings are somewhat a thing of the past. Kinda. Maybe. Not really. If you remember the last time (and if you don’t, I mean hey, go ahead and read it. *hint, hint, nudge, nudge*), I complained that typings were hell to use. The tool wasn’t good, the repository was crazy bloated and almost impossible to contribute to and you had to include a reference to a reference file for all your typings. The triple slash of nightmares.

With newer versions of TypeScript, definition files will be automatically loaded. That’s it. You drop a definition file in your project and you’re done. Now, this is nice, but it wouldn’t be enough for us to move back; this new tool, Typings, is what really helped us get back to TypeScript. It, literally, solves all the problems I had with DefinetelyTyped. Typings are versioned, it works a lot more like npm and you can pull typings from wherever you want! Those two changes are such a game changer, it’s hard to put into words how amazing those two changes are. If you’ve used TypeScript a year ago, you know. Ooooh, you know…

Compilation

Yeah… No, that’s still there. It’s always going to be, but it was not really a pain point before. JavaScript simply requires compilation in 2016 anyway, there isn’t much to say about this.

The Way Modules Are Imported

I wrote a little while ago how we had a way to have nice and clean imports when using ES6 and Webpack, but that would not be enough for TypeScript since the compiler has its own module resolution logic. However .tsconfig and TypeScript 1.9 came to the rescue! TypeScript now includes a node-like module resolution system and allows you to set various content root for your project’s modules. Once properly configured, you can have streamlined imports and as a bonus, depending on your IDE, they will be refactored when you refactor a class!

// Bye bye
import RestClient = require('../../Ez/App/Resources/public/ts/majisti/data/RestClient');

// Hello
import RestClient from 'majisti/data/RestClient'

Isn’t that just marvelous? Yes, it is.

You’re Forgetting Something!

Yeah, yeah I know, I’m forgetting mixins, which I complained about in passing last time. The truth is… Well, they didn’t really change. However, React moved away from those, preferring decorators or higher-order-components so we don’t really need them anymore and as far as other usages go… we haven’t encountered a situation where we needed them yet. I’m sure we will in time, but when we do, even if they’re still as clunky as they were before, I doubt this would stop us using TypeScript. It’s not like PHP is perfect (gosh, is it far from it), but we still keep using it. No reason TypeScript should get the cut either. Especially with all the benefits it brings us.

Alright, so TypeScript is Back to Being the Most Awesome?

I don’t know about the most awesome, but… yeah. Yeah it’s simply awesome now. Well, if you’re using TypeScript 2.0, otherwise my older post still stands.

Now… I think I’ll just drop a list of cool stuff. Yeah. Yeah, let’s do that.

  • IDE Support is a lot better. Not only Intellij IDEA and WebStorm got better, but VSCode is a pretty solid IDE for TypeScript. I wouldn’t use it for other stuff, but for TypeScript it’s great and fun to use.
  • .tsconfig is a godsend. That configuration file is so much more useful than before. Different module resolution, compilation options, file exclusion/inclusion and it’s thanks to .tsconfig that we don’t need to include typings anymore, TypeScript will just use .tsconfig's folder to determine the project’s root and look for .d.ts file. God bless .tsconfig.
  • All the good stuff I mentioned before still stands. I love strongly-type language. I’ll go into a bit more details on why later.
  • Module resolution is a million times better than before.
  • You can actually install typings from npm now! It’s still pretty new, but it has a lot of promise!
  • Allowing TypeScript to load JS modules. This was especially useful since we have a few test values we wanted a fake REST API server to share. We could have a JS file with those, loaded by both, our test cases and this fake server! Of course we lost type hinting from that JS file, but it can easily be solved (if you want to) by setting it as an interface: import jsFile as jsFileTsInterface from 'foo/bar/jsFile';.
  • A more “Babel” way to allow features. This is very useful to control how much we want to allow a project to use experimental features. We’re always aiming at maintainability here, so this was very good news that TypeScript would mimic this.
  • Abstract methods! Aaaw yeah!
  • Wildcards in module definition. Are you using CSS modules? Then yeah, this is awesome. I’m sure it’s great for much more, but right now that’s my big pain point.

Honestly, there are more nice little bits and pieces (probably a big one or two that I forgot too), but the real reason I’m glad we’re using TypeScript (and that it’s not a pain anymore) is just because I love strongly-type languages.

In Praise of Strongly-Typed Languages

Actually, I don’t think I care so much about strongly-type as much as I care about maintainability. It just helps in making an application that much easier to keep developing on. When a client comes to us, they’re looking for someone who will be able to keep iterating on their product.

With bare bones JavaScript (or even ES6), when you need to refactor something, you need to figure out where that method is used. Sure, you can find/replace, but you still have to be careful; the IDE can’t know if that usage of, say, that .clean() method really belongs to  InMemoryAuthentication. You slowly go through all of those calls, making sure they’re really the ones you want to refactor; or you let your tests tell you, that works too. However, with types like in TypeScript, my IDE knows which call of .clean() belongs to an instance of InMemoryAuthentication; once I refactor my interface or class, I can simply let it do it’s job and it’s done.

It also helps other developers in our team. Regular JavaScript, you’ll have this StringUtils module that has some nice helper methods to deal with, I assume, strings. That’s all well and good, but when I want to use the .cut(string, max) method that reduces a string if it’s too long, I have two parameters: string and max. It’s easy to assume they’re a string and an integer respectively, but that if that second parameter can be an array, representing a range of indexes where cutting that string is possible to try and cut where a space is? JavaScript won’t tell you, but TypeScript? You can bet it’ll tell you: static public cut(string: string, max: number|number[]): string;. Boom.

As a bonus, when I come back in my code 3 months later, I don’t need to open a file to remember what it’s asking me to pass a given method, my IDE helps me with that. It also allows us to work with interfaces rather than a concrete implementation of a class. That’s huge.

We are aware of things like JSDocs and yes we do use PHPDocs to properly document our PHP code. The truth though is we hate it. If we could completely eliminate comments, we would. I’m sure Steven will eventually go into great details about it, but quickly: we’re big fans of clean coding. If you have never read Robert C. Martin’s Clean Code: A Handbook of Agile Software Craftsmanship, you really ought it to yourself. Anyway, got side tracked here, I realize DocComments aren’t comments per se, but they still are comments, they’re an added layer on top of your code, it’s easy to forget to update them when you refactor something and those could and should be in the code itself!

All in all, what I’m trying to say is it makes us produce more, with a lot fewer errors made throughout and this, we hope, reflects in our clients having better bang for their buck. That’s always the end goal we have. We want to be a development business that works so efficiently our clients get nothing but value out of our services. I’m not sure how much of that people see when they interact with us, but that has always been our goal and focus. That’s why we didn’t stick with TypeScript last time and that’s why now, we’ll prone TypeScript whenever we get the chance to.

dollah