Sessions is temporarily moving to YouTube, check out all our new videos here.

Using TypeScript in Ember

Nikos Katsikanis speaking at Ember London in July, 2017
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

Add TypeScript to an existing Ember project with these practical examples.


What type of javascript, we are catching errors in the browser, right? Because, we are assigning a variable or getting a variable that's undefined sometimes or trying to do an operation on it I mean I get an error on the console With TypeScript you catch those errors at compile-time; You have a build step. The TypeScript compiler that looks at your source that's TypeScript. If there's errors, it won't actually output JavaScript. So this demo, what typescript is doing This is TypeScript here, This is JavaScript here, right? So if we do something like var i equals one then this is the output here, yeah? Now we can type this to a number, right, and we see that the output has basically removed the typing information. If we try and turn this into a string, it's gonna complain here, that i is not assignable to type number. So, we can also do classes, so we do class foo. So it's going to generate this here, right? Now unfortunately on this playground, we can't out ES6, but TypeScript can actually output ES6, so you won't have all this mess here of a constructor function; you'll have an ES6 class. Has anybody used any ES6 classes? Okay so Does anyone know how to make sudo classes in javascript? You have like the function and you can create a new instance of it, and you can assign properties to it. Well a class is basically some tactic sugar for that so it saves you having to write my function.prototype but there's a lot of stuff you can just write class. So in TypeScript, you can add... You have this concept of fields, right, that run on a class You say foo one You have something called a constructor. And you can see it takes a parameter called baa of type number. Okay, and you can say something like this.baa equals this. Okay so we have to declare everything that is in the class like so. So we can see this is a number. So this is like, this typing information here is removed from the output. So you interact with this stuff in your code and then you have the output here. So if we can do, let's create an instance of this class, like Var test equals new Foo. It's gonna complain here because we have not supplied all of the parameters to it. You with me so far? So what do you think we could get away with supplying here? String, like this? Nope, it's not going to let us do this because there's a type called number. So this immediately gives an advantage over basic JavaScript. We know from the compiler what we're expecting here. We normally would find this problem in the browser, we'd have some weird error going on but here we're catching it here like this, right? So put it in here like that. So that compiles. The only other major thing I want to talk about here is this thing called interfaces. Any of you know what interfaces are? It's like a contract that this class must fulfil. If I do interface Ifoo, and we see in here you must have a free property of type number and this one here. Now what we can do is we can force this class to implement this interface. No. So it's already happy here. Now if we say make this change to that it's going to complain and say that it does not have... Class foo incorrectly implements interface Ifoo, foo is missing in type foo. So what that's really useful for is say you have a bunch of objects, that you wanna enforce them kinda conventionally. This is really useful. So in terms of open source, I have something called Test Recorder. And what I've done is I provided an interface for different integration test frameworks that you implement in order to get it to be compatible with the Test Recorder. So if we look at the source, we have this thing called codeGenerators. So I've got this thing called the ember generator and the night watch generator and they both implement this interface here. So, what this is saying is that anything that implements ICodeGenerator must have all these properties, it must have a description, string, and also have a bunch of functions. What this means is it must have a function that takes a property called a parameter of type string and outputs a mutation entry, which is a core JavaScript class. Does anyone remember my Test Recorder talks? Anyone remember that? Well the good news is it's now a Chrome Extension. You just click, you can instal it from here. And you can click about the page doing things. Well if it was a single-page app then it would. So what it does is it listens for changes of things with IDs. You can go into, go Chrome and type in test recorder, you can download it. So this is an example of, this is like a lab here that I showed last time, and there's code generated here. So Ember and TypeScript. So I have an existing TypeScript, a sort of Ember project. And what you have to do to get it to work. Really small, isn't it? So if you want to add TypeScript to an existing Ember project, you have to download TypeScript, Ember CLI TypeScript, and these types of Ember. This will allow you to strongly type various aspects of the framework. Now this is all about Bleeding Edge. This thing here is maintained by a guy I know, and even he doesn't know, he's still testing out new things with it, so it's a bit bleeding edge, from what I've seen last night, it seems to work. Once you instal Ember CLI TypeScript, it will give you a TypeScript config, which is what you need for the thing to work. So what the add-on does is it looks at TypeScript files in an imported directory and it's gonna be mixed in with JavaScript files and before it gets bundled to broccoli it converts it into an ES6 class, which is what then gets taken as a normal Ember class, right? It has paths to your project. So what I've done was I created a TypeScript component near here, and this is just a very, well it doesn't actually do anything, it's just a TypeScript file that gets compiled into JavaScript. So if we go to our TypeScript route, we have two TypeScript components, right. So the first one is a TypeScript component here which just renders an input, right? That's what we're seeing here. And as we type, it's outputting the value mutation, so that's just like, it's a TypeScript file that compounds to JavaScript, and is viewed as normal. Now the second one is the one that has some TypeScript type stuff happening. So what I had to do was I used some annotations, so I had to instal this package that ROW blue like this, or there's a babel plugin transform class properties in this thing; he's got a blog about it. And instal Ember decorators. You can actually use this you can use this in your ES6 classes. And so with that thing that I just showed you you can use for creating properties like this, you can write down like that, and you can have actions written like this. And here we are using, this is just class syntax. I also have this service, so I have a service called foo. And this is being injected via... This is the declarative syntax for services, so you don't have to write inject, you can just declare it like that. And the service itself, I just created it a few minutes ago. So here's a service that has an interface. So I'm creating this service like this, passing an object. And that object itself is typed to this interface here. So it has that. It's just saying the service must have a number. Now you... Can you imagine an app that has like 10 different backend services for different objects, that have Ajax goals? You could create a service that says, "I must have a put request," and this function must return a promise and fact, and all that kinda stuff. So if you have like a big team you can just create these interfaces and you can share them. You have full access to the TypeScript language, so you can create a whole bunch of non-Emberish type things, and use them to get the benefits of TypeScript. That's all there really is I want to talk about tonight, so this is showing it working, this is the component here. It's rendering numbers, so if I go to my TypeScript... So I'm just rendering the keys. That's what we're seeing there, so I'm just showing you that it works. So, not a very exciting talk, but you can start using it. - [Audience Member] What's next for the add-on itself, and what's missing at the moment? - Well so far, I haven't found any glitches yet, but I just started using it last night. So, yeah we were online talking and like, "Okay I think I found something I can talk about in the meet-up tomorrow." So, I mean the TypeScript compiler is understanding this right, so... Oh, by the way this component also implements this interface here, so see how we've got like these keys here and I've got this... Even like the actions you can force to be of a certain thing, so say if I want this to be a function, that turns a number, then it's gonna complain here that... I think it'll throw a compile-time error and say, "Hey, you're not returning a number." Nope. Okay that's something I need to check with the guys, 'cause that, normally here you'd want to have to return a number. Your action's gonna return values now, well handle actions. Like if I take this string, it should complain that, all right so here it is. Yeah it's complaining that this property isn't a string, right? And uh... Oh oops, that was a... So if we comment this out. All right so look, it's complaining that the action is not returning a number now. But when we see return two, it's allowed us to compile. It's a bit cheeky. So maybe we need to force the add-on to stop develop process. And I'll talk with the TypeScript people about.