Presented at Web Unleashed on September 16-17, 2015 in Toronto, Canada
More info at www.fitc.ca/webu
Why TypeScript?
with Jeff Francis
OVERVIEW
TypeScript is a type-checked superset of JavaScript that benefits medium-sized to complex JavaScript projects. Why would you want to learn a new language, instead of another JavaScript framework? You have all this existing JavaScript code, so how can you adopt something new without throwing the old stuff out?
This session is about the benefits of using TypeScript on top of JavaScript in your projects, and demonstrate step by step ways of migrating an existing JavaScript project to TypeScript. We will dive into code generated by the compiler and look at resources and tools that make working in TypeScript a pleasurable experience.
OBJECTIVE
To understand when it’s a good idea to use TypeScript.
TARGET AUDIENCE
JavaScript developers.
ASSUMED AUDIENCE KNOWLEDGE
Intermediate JavaScript experience.
FIVE THINGS AUDIENCE MEMBERS WILL LEARN
The basics of TypeScript – types, classes, modules, and functions
How TypeScript’s design makes getting started simple and helps projects
What compiled TypeScript looks like and how to debug
What tools can help take advantage of TypeScript’s type information
How to migrate a JavaScript project to TypeScript
19. var isBatting: any = false;
var inning: any = 6;
var teamName: any = "Blue Jays";
var runsRecord: any[] = [1, 6, 3];
20. var isBatting: boolean = <any> false;
var inning: number = <any> false;
var teamName: string = <any> false;
var runsRecord: number[] = <any> false;
21. var pitch = function(type) {
if (type == "fastball")
return 170.5;
else
return 123.9;
};
22. var pitch = function(type: string): number {
if (type == "fastball")
return 170.5;
else
return 123.9;
};
23. var pitch = function(type: string): boolean {
if (type == "fastball")
return true;
else
return false;
};
var x = pitch("curve");
console.log(x – 10); --error
35. var player = oldPlayer;
for (var i = 0; i < trades.length; i++) {
var player = trades[i];
trade(player);
}
expect(player).toBe(trades[trades.length -1]);
36. var player = oldPlayer;
for (var i = 0; i < trades.length; i++) {
let player = trades[i];
trade(player);
}
expect(player).toBe(oldPlayer);
37. for (var i = 0; i < trades.length; i++) {
player = trades[i];
trade(player);
}
58. File file = new File("some_file.txt");
BufferedReader reader =
new BufferedReader(new FileReader(file));
String line = reader.readLine();
while (line != null) {
System.out.println(line.toUpperCase());
line = reader.readLine();
}
reader.close();
File.open("some_file.txt") do |file|
file.readlines.each do |line|
puts line.upcase
end
end
59. import java.util.Comparator;
public class PlayerComparator implements Comparator {
@Override public int compare(Player p1, Player p2) {
String name1 = p1.getName();
String name2 = p2.getName();
return name1.compareTo(name2);
}
}
75. interface Findable {
whereAreYou(): string;
};
class Player implements Findable {
...
whereAreYou() {
return "Playing Baseball";
}
};
var player: Findable = new Player();
player.whereAreYou();
76. interface Findable {
whereAreYou(): string;
};
class Player {
...
whereAreYou() {
return "Playing Baseball";
}
};
var player: Findable = new Player();
player.whereAreYou();
77. class Player {
...
whereAreYou() {
return "Playing Baseball";
}
};
interface Findable {
whereAreYou(): string;
};
var player: Findable = new Player();
player.whereAreYou();
78. late interfaces let you write simpler types
SimpleBeanFactoryAwareAspectInstanceFactory
AbstractSingletonProxyFactoryBean
http://www.quora.com/What-are-the-most-ridiculous-Java-
class-names-from-real-code
I’m going to be giving a talk on “Why Typescript”. I’m not intending this to be a balanced pro-and-con presentation it’s really to present why I think it’s probably a good idea to use TypeScript for any medium sized project+
To give you a little context on who I am… I’m a developer at flipp, and we have for years used typed javascript. It wasn’t TypeScript, it was the google closure compiler and standard google closure library. I still really like and appreciate google closure, but more recently TypeScript has really made it stand out for Typed Javascript, and I believe that for most developers, they’re better off using TypeScript.
So… before we can say why TypeScript is so good, we need to get a basic introduction to what typescript is… Hopefully you’ve come to this talk because you have some idea, but we can review the fundamentals.
So… before we can say why TypeScript is so good, we need to get a basic introduction to what typescript is… Hopefully you’ve come to this talk because you have some idea, but we can review the fundamentals.
First of all, it’s a superset of Javascript. It isn’t really a new language, its more a bulked up version of another one. This property is very beneficial for practical purposes, but it also means the real benefits of the language aren’t coming from some big different paradigm shift
The other main aspect of typer script is right in the name… it’s typed! I love typed javascript, and I hope after this presentation you will too…
So… we’re adding types, and we’re adding new things on top of javascript… what does that actually get us… why is this a good idea?
Well… it’s very much like javascript, but the features added are specifically to address the need for scale in development. Developers are making programs that are bigger than plain web pages… this has been true for many years now. However JavaScript up until ES6 really hasn’t been changing much to meet the requirements of bigger teams and bigger codebases.
JavaScript was the winner by default. It was designed in under 2 weeks, and it has won because the web won. JavaScript is a hugely popular language because it’s easily available to everyone, and the web is so simple to create visual programs.
This is a list of different transpilers that target javascript. It’s from the coffeescript github. The biggest ones are probably dart and coffee script, but clearly developers feel something is missing with JavaScript, yet need to target it as an execution platform. It’s kind of the assembly for the web.
So the question is… what does typescript that adds scale. It’s easy to say… javascript can’t scale, and no one really loves it even though they have to use it, but what specifically can TS do to improve code.
I think it breaks down into 3 main categories. First, there are alots of trivial little issues that come up when writing JS code, that TS addresses. The second is that TS code is generally easier to read than JS code. And finallly, when it comes to changing things, it’s a lot easier to do so with TS than JS.
This first set addresses even small programs and beginners. It isn’t really an issue of scale, except that as small problems grow, you end up with scale issues
Adding types to programs prevents bugs by finding them early, hopefully as you type them. These simple bugs sometimes make it into prod and blow up in production, but usually they pop up immediately after loading your web page. It’s better to have your compiler find them quickly.
Here’s a simple example. We’re setting the variable message to a string with the inning set to the end. This code looks correct in isolation, and if you saw it in the middle of a function you’d think it was right.
What if it turned out that inning wasn’t a string at all. But an object literal? This sort of bug happens all the time. Often there are two code paths, and in one path it’s a number, and in another its an object. Wouldn’t it be nice if this couldn’t happen?
It turns out that your code already has types. These types are implicit, and your program relies on them to be correct. You may not know what they are as the programmer, but your program depends on them to exist. Not declaring your types, doesn’t make this problem go away.
Heres some more variables. A bool, a number, a string, an array. They all really do have types.
In typescript we can use the colon to define what those types are. This looks pretty similar to any other typed language, but you see its not a big change to the JS.
JS does have types, its dynamically typed, not untyped. The problem is that the type system that JS has, only knows about ONE type… it’s called the any type? You got a type? It’s the any type.
This is what it looks like in TypeScript if you wanted it to be that way. TS types can be exactly JS just by making everything any.
This works two ways actually… you can say a variable is a type, but you can also claim a value is a type any… and then it will match always…. Of course if you do this… your program will break.
This is a pretty typical javascript function. Takes a pitch and returns a speed.
This is what it looks like with types… the type of pitch is a string, and it returns a number. Of course, typescript can figure all this out implicitly through type infrencing.
This is what it looks like with types… the type of pitch is a string, and it returns a number. Of course, typescript can figure all this out implicitly through type infrencing.
Something that happens quite often in JS code is implicit conversion. Often between numbers and strings.
Implicit conversion is a bear trap… typescript removes these kind of trivia items. These bugs are found
This is a source of much confusion in JS. The scoping of this is determined by how a function is called, not by where the function was defined.
In this example, if you imagine this code inside a member function of some player object. It seems clear that the player is going to catch then throw the ball once the catch promise completes.
It turns out that you have to smuggle this value along in a temporary variable to get the lexical scoping you were looking for.
In typescript there are what are called arrow functions… the function is defined by a fat arrow, and in this case the lexical scope of the arrow function is bound to this. It used to be that you’d have to use extra variables or a bind call.
Prototypes in JavaScript are often an object of confusion, and then to those who understand it, some sort of point of pride
This is what a class in javascript looks like. Strangely a function is a constructor, in fact any function is a constructor. And in that constructor this is bound to the newly created object in the new operation.
Adding functions to this constructor is done through the prototype property. This property is copied into the proto property of any class instantiated with new, and is what is looked up to find properties. While ok when you get used to it, it isn’t really like other langauges, and some developers choose to avoid new, and instead make their own form of constructor functions that return object literals.
This is what a class looks like in TypeScript. It looks far more similar to other programming langauges, and essentially codifies what other frameworks have done to try and make creating classes more regular. You can define the property types, and the constructor is called constructor. The member functions are simply defined as part of the class.
Note that this is from ES6 (except for the types) so it should be fairly consistent in thefuture.
Inheretence is also a lot simpler with this class context. Previously to do this, people would go through certain prototype exercies to properly do inherentence, but having a super call was usually quite awkward. Here we have a proper super method that we can call in constructors, and also in any other functions.
Classes help build structures in the code that will lead to better code quality and having one way to do it will help.
var is how we define variables in javascript, and typescript adds two more ways of doing it, both from ES6
In this function you see what happens when you try and shadow player with another var in a block. Player ends up being the last value in the loop. Of course you’d never write this code correct? Well, often this can happen when you move logic around, maybe copy paste from somewhere and you get bad results.
Let allows you to have block scoping for your variables. This means it wont clobber, and its easier to understand the behaviour
Even worse however, is if you forget the var. Now player is on the window somewhere. This leads to all sort of interesting bugs. Typescript of course will detect this sort of bug.
Code often has magic numbers, or constants. But you can’t make any constant constant in JS.
The const keyword means that Typescript finds this bug and flags it. Note that ES6 will silently fail on this, it enforces the const by just ignoring it… which is one way to avoid a bug… maybe create another one
Let’s go on to the next topic. Making the code more readable
One thing that types do to help readability. They tell you what the last programmer is telling the compiler.
This looks like typical javascript, but to a reader it may not be clear what the scope of the second parameter can be. When we use dynamic things like strings and object literals, that context is lost.
Typescript can use enums for example, but it’s not this specific example that’s important it’s that this sort of information is used all the time when understanding code.
Often we can use JSDocs. In Closure Compiler these docs are used to check types. However these types always have the chance of rotting in the comments if you don’t use the compiler to check them. I know in ruby devs always want to use YARD to tell the types, it’s because without them it’s very hard to understand what’s going on.
So… for readability… everyone knows what this means right? The most important function in the entire web.
So when you see this? What does it mean? What’s players? Well its wrapped in a jquery object, but what are we really dealing with.
Without types being clear on selected, any of these can actually be the call. Each one of these will be slightly different in meaning.
Another pain point in JS is just how the program stucture in the large is put together. Typescript from ES6 adds modules.
The canonical way to add new code to the web by an ordered list of script tags doesn’t lend itself to modularization very well.
Many people have written loaders to overcome this, some of which do things like this… but hopefully not in production
In general, most developers are already compiling their javascript, if not to minify, but to glue together large seconds of code. This is fine, but also further reduces the barrier to TypeScript, which is just another compiler….
Even if you compile, I’m sure many of you have seen code like this. This isn’t really a code loading issue, it’s just that you often want to define modules in pieces, and JS gives you no easy way to do namespaces. This code creeps me out….
In typescript you can add namspaces. This is the class example earlier wrapped in a module.
And we can import and export our namespaces and objects using import and export. There actually are several ways to do this in typescript to be compatable with different ways people like loading their code. Creating a firm module foundation however is a big help in scaling the code.
Let and const also help with readability. Especially const when you use it not only on those magic numbers, but also just on varialbes you know won’t be re-assigned. That means readers can easily understand what is changing and what is not changing.
Because typescript has IDE support… you can more easily read because you can more easily play. Reading then becomes more interactive, as you can scrub the code to find out what it means and what other values are available.
But… I’m saying things are easier to read… and there may be baggage people have about typed langauges. I remember working with Java 15 years ago.. .and hating it.
This isn’t a fair comparison for today, but historically dynamic languages had a surge in the mid 2000’s and at the time type langauges like java look like coe on the left, while dynamic languages looked like code on the right.
File file = new File augh
Even worse was sorting things! This was the way to sort values in Java… Wasn’t this a result of the need for all the types?
This isn’t types… it was closures. Dynamic languages used blocks and closures to vastly improve their API design. You didn’t need classes for everything, when functions and object literals could do the job.
TypeScript doesn’t need to have those old api’s, and as well see soon, it also dosen’t need to have crazy interface hell to be used nicely.
The final part… types help you discover change impact… so you can make changes easily
If you can’t read your code easily and play with it, then it’s hard to change with confidence. Test coverage is lovely, but sometimes in the face of real change, it actually can’t help you, because it’s testing where you were before, not where you want to go.
Types help a lot when making changes, because they ripple the effects of the changes you make through the codebase correctly.
Let’s talk about duck typing, a beloved topic of dynamic languages. It comes down to this quote….
The general idea is that all you need to do is call the function, and if it responds than you’re in.
Well… I think there are 2 problems. First it’s more like quack typing… because it typically means you’re only checking one member of the object, the second is that failing at runtime isn’t really typing at all.
Let’s look at an example though of how interfaces let you do a real sort of duck typing… Use implicit any…. And discover the types.. Then move to arrays.
So how do I get started using TypeScript in my projects?
The good news is TS is not not JS, so that means that your existing code will have a relatively easy time with TS
TypeScript not only works with JS today, its attempting to stay very close to the ES6 standard.
The mechanics for doing this are d.ts files. These files type the untyped and lift them into typescript’s world.
Now… in google closure, it was always tough to get coverage across all the libraries you’d want, but typescript has amazing community support. The github defintatelyTyped has several definitions for lots of JS… this is just a to co…
Heres an example of what the jQUery one looked like. If Jquery can be typed, your code can be typed.
There’s also lib.d.ts which includes all the standard browser envirnment. Never have to worry what window.getSelection does again by googling it.
Let’s look at an example of dts.. Then go to playground and show the types.
All this ipossible because unlike most typed languages. Typescript really is bolted on top of Javascript, and this means it was designed for tretroactive typing. I think this is acutally pretty special and has neat implications. this lets you have the best of both. Let
Let’s look at this class, pretty typically defined, with an interface, but implemented by the class.
As you may have noticed in our ducky example, the interfface doesn’t actually need to be implemented by the class, ts figures that out.
And in fact, because it’s retroactive, the interface can come later…. This is how d.ts. Works and types code that was already written.
This strategy however has implications not just for old code you’re lifiting into typescript. But code you’re writing new. A lot of code in types involves guessing… would you have guessed you needed these class interfaces in java? This is why dynamic languages feel fast to work in, because you’re guessing less. If you can write first and interface after, then you guess les.
Also late interfaces let you work with the common issue of partial data. Sometimes you have an entire object, sometimes only part.
There are two simple ways to approach adding typescript to your project.
First… if like the other libraries, you have stable code.. Then just use d.t.s. This means you get the most benefit for typing without having to change deep existing code.
But if your code is still changing, its simple as renaming js to ts… Then compile and fix the errors. Then after that is complete, migrate your classes to new structures. But TS is essentially very much JS, and even the classes are ES6 essentially.
Show it just works, then add the classes to the typescript, and type the print…
As you can see, TS works well with others. It isn’t microsoft’s kingdom
These all work together, Angular 2.0 is written in TypeScript. React even has JSX support in the language.
Heres an example if you’re using react, where you can have types in your component definitions.
And compilation, it’s supported by grunt, gulp, or even make as we use it. All these build pipelines can be set to watch. Tsc – watch.
… if you like make it’s just a command line…
And in for IDEs, it is broadly supported. There are plugins for VIM, emacs, but VisualStudio is very good. I’ve been demoin from visual studio code.
TS is easy to try, so theres no excuse, Get on it!