Video details

Typed JavaScript? For real? The type annotations proposal and what it’s all about


A major earthquake has hit TC39, the JavaScript standards committee. A proposal for adding type annotations to JavaScript has just landed on the committee and has been approved for Stage 1. What is this proposal all about? How did it come to be? What is the motivation behind it? What are its pros and cons? Why are some people excited about it, some wary, some angry, and some afraid?
As one of the writers of this proposal, I will delve into the details of the proposal, and try to answer all the questions above.
PUBLICATION PERMISSIONS: NearForm Organizers provided Coding Tech with the permission to republish NearForm tech talks.
CREDITS: NearForm YouTube channel:


Good morning, everybody. Type JavaScript. How many of you are using TypeScript and not JavaScript in their Node code or front end code? Perfect. I use JS Doc typings, but it's like almost the same. A lot of you, how many would wish not to need to transpire the code that you're running? Probably the same amount of hands raised, right? So I'm going to talk about type JavaScript. This is a proposal for TC 39. We're going to get into it and what it's all about. As I said, it's a formal proposal for enhancing JavaScript that will change JavaScript development forever. And it's a proposal for adding types to JavaScript. A little bit about me. I'm old, like 80s old. Always will be a developer, but what I love to do is code. I'm currently an architect at Roundforest. We build complex trophy sites. But this is more interesting. I'm also a member of the group that is writing the proposal for TC 39. And by faith and chance, I'm the original author. Little Dan approached me after I wrote a blog post about JSDoc typings. He corrected a few typos and a little small mistakes and they said, Well, I have this idea about a proposal. And he talked to me about it. And I said, oh, yeah? He said, do you want to write it? Like a week later it was written, so I'm lucky to be here. And it's very exciting because it's something that I've always wanted to do and we'll talk about that later. Why? But I am one of a group that is doing this, writing this proposal. But the opinions are mine and mine only, and not necessarily all the members of the authors of the proposal. This is the disclaimer. Definitely not my employers, and especially I do not speak on behalf of the TypeScript team. The TypeScript team is part and they are on board with this proposal, but I do not speak on behalf of them. Also, the proposal is officially part of the TC 39 process. So whatever we say has weight, obviously, but in the end, it will probably be different than what I'm showing you today. So it's a long process which we'll talk about in a second, so we don't know what's going to be at the end of it. This talk will be about this proposal. Where, what is it and why was it proposed? So let's talk about the where TC 39. What is TC 39 for people that do not know? It is the committee. It's not a committee. It is the Committee for the Standardization of JavaScript. It's called Echoscript for various legal reasons. Thank you, Oracle. But it's basically the committee that standardizes JavaScript. And amazingly, the process is very transparent. I go through all the meeting notes. I'm like one of those crazy and everything is written down, all the arguments, all the discussions, issues in GitHub. Very, very open, very, very transparent. Feel free to go in there and each year they bring out a new version of JavaScript echoescript 20 15, 20 16, 20 17, et cetera, et cetera. And with new features basically array at string includes async await, top level await, all these kinds of things. Work come out of the TC 39 standardization process and the process goes through a very specific set of stages, which I will talk about. Stage Zero is to be proposed. It's a thing that we want to propose to TC 39. Stage One is the committee meets, I think, every two months, something like that, and they listen to the proposals and if they say, yeah, good idea, then it's Stage One. The proposal doesn't have to be exact, it can be like a rough draft or an idea, but enough so that the committee can say, yes, it's a good idea. Let's further go into details. Stage Two is where we go to the committee with a very detailed draft, basically a spec, and say this is what we want to do. If they accept it. Stage two. If they don't, back to the drawing board. We've seen these things. Sometimes proposals reach Stage Three and then go back to Stage One and sometimes disappear forever. Stage Three is where all the rough parts are done. Every little tiny bit of detail in the spec is cleaned up and it's waiting for implementation. When the committee says to Stage Three, then like WebKit and V Eight and JavaScript Core and Spider Monkey and all those JavaScript runtimes, at least two of them, I think, I'm not sure about the details, need to implement that feature and check that it's fine. Once the vendors, the runtime say that it is fine, it gets to Stage Four and that's part of the standard. Okay, let's talk about what it is. First of all, it was proposed on March this year, accepted to Stage One, which is great for me, accepting doesn't mean that that's it, it's going to be part of the standard. It just means, oh, it's a good idea, let's discuss this further, let's talk about the proposal. So this is JavaScript, right? Regular JavaScript, a function add that accepts two parameters a plus B. A can be a number, a string, an object, a function, whatever. If it works, it works, if it doesn't, it doesn't. That's JavaScript for us. This if the proposal gets accepted, and I will probably get tired of saying if this proposal gets accepted. So we'll assume that it is no guarantees, obviously. So with this proposal, this will be legal JavaScript. So A is a number, B is a number, and the function returns a number. You know this from TypeScript or flow, if you're using flow type annotations, those are the type annotations which say A is a number, B is a number, C is a number. Will this pass in the future? JavaScript if I say that A is a number and I pass it a string somebody has an idea, will this pass? Yes, that's why it's true. They're the second parameter. It will pass because the idea of type annotations is that they are only annotations. JavaScript will not look at the annotation and try and figure out whether the arguments are legal or not. The original name of the proposal was types as comments. So you have the type annotations, but JavaScript will treat them as comments. So yeah, treat them like comments. And what is the syntax of the types? The proposal says we don't care, this is legal. It's not legal TypeScript, it's not legal Flow. I don't think there's any type system out there that it is legal in, but it's legal. It will be legal JavaScript if this proposal is accepted. So these areas with the type annotations, we call them type annotation syntax space. We will be carving out space in the JavaScript syntax for type annotations and for the JavaScript runtime to ignore those type annotations. And we call them the type annotation Success base. And when I go into detail about the proposal, I will talk about all those type annotations syntax spaces that are reserved for type annotations. For example, more type annotations like type foo equals function, return value, et cetera, et cetera. Those are more type annotation syntax bases. Obviously, as you can see, it's the same syntax as TypeScript. So most legal TypeScript and Flow and Hegel. By the way, there are more type systems out there than TypeScript and Flow. It's the same places. So whatever a TypeScript you have, most of it will be legal JavaScript. And obviously this is not a coincidence. Those spaces were chosen in this proposal so that they can correspond. But this is not TypeScript, this is not Flow, this is not Hegel. This will be legal JavaScript, this will not be legal TypeScript. But what do I care if the type annotations are ignored? What do I get? Okay, why do I need type annotations? And the answer is there will still be third party type checkers like TypeScript, Flow, Hegel, and others that will check your type annotations, just like Es. Lint checks your code TSC or Flow will check your type annotations, but JavaScript won't JavaScript won't say that a variable is unused. Okay, but used lint will. JavaScript won't say that you're trying to pass a string to something that accepts a number, but TypeScript will during the build process. So, summary of the proposal we reserve syntax space for type annotations. They are ignored by JavaScript. Runtime are assumed to be checked by third party type checkers like TypeScript and Flow and correspond to the same syntax space that typescripts and Flow and others use roughly. So we announced the proposal on March 9 and the Internet exploded. I've never seen seen a proposal get this much Twitter space if you want. Most of it was good, lots of finally and yes, and those emojis, but there were lots of criticism mostly good criticism, some were well, Twitter, but really mostly good criticism. And the issues in GitHub are fine, and there's lots of discussions there, and I want to address those criticisms in this talk and show why we chose the path we chose. So let's talk about the why. Why add types at all? It's a good question. A lot of people ask that it is not a trivial feature to add to JavaScript. It's not like whatever string include. Obviously, for a feature of this size, the benefits have to be substantial. And I give two graphs as an answer. It's actually two graphs and a half. This is the number of PRS in March 2022. Notice JavaScript and TypeScript. TypeScript has almost the same number of PRS as JavaScript. The JavaScript community is, and we've seen this is using TypeScript heavily today. They are using types. They are used in the field and have proven the value. Obviously, if they have not proven the value, then people wouldn't use them. We're not dumb. State of JavaScript 2020 static typing is the most requested feature. State of JavaScript 2021 static typing is the most requested feature. And if you're still not convinced, this is from this month. Remember, TypeScript was almost the number of PRS was almost like JavaScript. Well, this month TypeScript passed JavaScript in the number of PRS in GitHub, which is amazing. So I don't know, people want Types in JavaScript, so is it worth the complexity? I think obviously, yes. Three more reasons. Not that I had Types adopted, and we'll go through each of them. Types are difficult for beginners to grasp valid criticism. JavaScript is simple. Simple for developers, yes, but my daughter, she's 15 years old, she's starting to learn computers programming, and she started with well, Java. Sorry, but yeah, not a good starting language. But she's fine, she understands Types, she's using Types. She gets it. It's not that difficult. Yes, if you're starting to learn JavaScript, then you've already learned JavaScript and then adding Types after the fact, then that becomes more complex. But if this proposal gets accepted, types will already be a part of how people use JavaScript initially, so I don't think they will add bigger complexity. And in the GitHub issues that discussed this, there was a teacher which said new programmers searching, for example code are likely to find TypeScript and flow examples and then wonder why it results in an error when viewed in the browser. So people copy paste code, put them in the console or the node rapple, and it doesn't work and they don't understand why. Beginners don't forget. So this is good, I like that. In other words, whether or not type annotations are everywhere, so beginners need to learn them. This one's really weird. Types, most of them are good. I don't get this. Types increase the payload in web apps. Of course, types make your code larger. So do comments. So does indentation. Do we want to get rid of indentation. Do we want to get rid of comments? No. Do we want to get rid of type annotations just because they make the payload larger? No. Why don't we? Because we have minifiers, remember those? Where they can minify the code, remove the type annotations and we're good. So type annotations in development don't need to be removed. No need for minifiers. When you're good to production, just run the Minifier and you're done. This is one is good. I used to be there. I don't like types. Types are shite. I have a colleague of mine who was there in the days of when I thought just like that. Even if I think about that now, today types of shite, it's not about me, it's about you. It's about the community. And the community wants types. So it doesn't really matter what I think or he thinks, or she thinks or they think. What matters is what the community thinks. And the community, as I've shown in the graphs, wants types. Okay, so we want type annotations, but we already have TypeScript. Why do we need to extend JavaScript? And this is a good question. Well, most of them are good except the payload thing. Why not just continue using tooling? There are three answers to philosophical and political people. I come from the come from the 80s. We have forgotten our roots in scripting. Write code, run it, write code, run it. Especially in front end. We go through this lengthy build process and we transpire and we do source maps which never really work. And we add complexity and complexity and complexity on it. We have become addicted to tooling. We cannot not use it anymore. Junior developers don't understand how this tooling works. They don't they don't understand the build process, especially in front end, but also in back end. Senior developers don't understand. Seriously, nobody understands. That's why we have created react app and remix and Next and all that because we don't want to understand it. But it's there. And when it goes wrong and when we need to combine it with other stuff, it gets hairy. Tooling is now basically what I think Cargo called. It used to be very important, a guarantee. But today I don't think it's necessary anymore. It's still necessary for production built, obviously, but it incurs tremendous development time, overhead and complexity. Philosophical answer JavaScript is the only language where we're coding in one language TypeScript and flow, and we're running it in another. That doesn't happen in Python, that doesn't happen in Ruby, that doesn't happen in Java. Well, sort of. There's a growing rift between the code that we write and the code that PC 39 standardizes and that is not good. We need to mend that rift. We need to bring these two languages together. The pragmatic answer, not a philosophical is types of come on, it's everywhere. All modern tooling. If you think about Es, Lint and Minifiers and whatever tooling you're using, they must understand TypeScript syntax today think of es build and all that everybody now understands TypeScript and that is not good because TypeScript evolves and they need to keep track of that. Not only that, TypeScript now has a monopoly in type systems I had a lunch discussion if I want to build a type system today, I can't that competes or works with TypeScript or extends TypeScript, I can't do that. TypeScript or Flow, I can't do that because the monopoly this proposal simplifies the tooling tremendously so and the political answer too is I think TC 39 should be the arena for enabling type systems that will be almost in everyone's JS code in the future. OK, so we want Types to be part of the language, but this will not enable us to standardize Types in the future. People got that very quickly because JavaScript has to be backward compatible and if we're saying we're ignoring content type annotations we will need to ignore them for now and for the future. True but when Denise arises love will find a way we will find a way if we want to standardize type systems we will find a way we'll figure it out why stop at ignoring type invitation? This goes the other way okay, let's do it the other way as long as we're doing Types, why not embrace TypeScript syntax? And the answer is microsoft and Facebook with Flow and other type systems want to continue experimenting there in that area standardizing it will stop them in their tracks and we don't want that. We want them to continue experimenting types in JavaScript are not done. So that's why I don't want to embrace that way we don't want to embrace and we want to continue experimenting with other type systems I just saw Ethno, which is really interesting if this proposal gets successful, people will want other type systems and the other one is TypeScript is huge standardizing, it will never ever end. The option is build a type system of our own you have two options here cleaner and simpler. A lot of people say oh, type script is too complicated, let's make a simple one but the reason TypeScript is complicated is because JavaScript typing is complicated. For example, pick you want this code Pick to show an error there because pick chooses creates an object only based out of A and B. Okay? A type system that enables that is very complex. Enables other stuff too. So type stuff is complicated for a reason. The other one is it's too complicated. Let's make it cleaner like Haskell and OCaml in reason. But that won't work because JavaScript you need to change JavaScript to have it be a cleaner type system and you can't change JavaScript. The third argument is well, let's go all the way let's do runtime type checking. This is an interesting option if you think about it most static languages today do not do runtime type checks. C plus plus doesn't do runtime type checks, JavaScript doesn't do runtime type checks. They do, but like right on the edge, all the type checking is done in the compiler, not in the runtime. It's interesting to think about that. Having said that, TC 39 said that we should check this aspect of this proposal. Another one is let's optimize based on types. If I know that A accepts a number, that function accepts a number, I can optimize the code the runtime, and the answer is probably not. There's a Twitter discussion on that from Matthias Binance. I hope I'm saying it correctly on why this will never be feasible in JavaScript as it is today. Okay, I'll skip the summary because I want to talk about the proposal. As I said, caveat, this will undergo considerable changes. It's just a first draft, but let's talk about what it is. Function A, this is in functions we have type annotations for parameters and for the return value. Big question where does the type end? How does the JavaScript note? What to ignore? And in comments it's easy. When you look at a slash star, you find the star at the end. That's a comment. How do we know where a type ends? We can't deliver it by comma, like okay, when's the next parameter? Because there can be a comma inside the type. Okay, we want to deal with that. And the answer we found, and again this can change, is we search for the comma, but if there are parentheses, like angle brackets or square brackets or parentheses, or that we count them and balance them and ignore anything in between those balanced parentheses, okay, that takes care of 95% of types in TypeScript. The others where this doesn't work, if you take TypeScript code today, then you just surround them with parentheses and actually it's valid TypeScript. So some amount of change in TypeScript will need to be done, but this can be a code mod very, very easily, a code modification. And this will allow continued evolution of the types without breaking JavaScript code separately, because TypeScript and flow and others can build inside that space very easily. Okay, so functions, variables, definition of variables, types we know this from TypeScript and flow interface from TypeScript and flow, or maybe just TypeScript, not sure. Class properties, generics, very important. Obviously importing and exporting types are supported in this proposal. There are things that aren't oh wait, no way. There are things that are like what do we do now is as because flow and TypeScript have different syntax for typecasting generic function invocation this is interesting. Why is generic function invocation problem? Because it's not valid JavaScript. The less than JavaScript treat it as a less than and not as a generic function. We're thinking about dealing with that. This parameters and declarations which should be in DTS files anyway, function overloads which typescripts and flow allow what do we do with that? I don't know. We'll think about something abstract. Classes may have runtime semantics, member modifiers, public read only, et cetera, et cetera. Maybe we're thinking about using a Sigil. Or Sigil. Never know how to say that. Percent. Public percent. Read only to say just ignore those and TypeScript up. They will not be in the spec I passed the time. I'll try enum's name fixes and parameter properties. These are TypeScript constructs that create JavaScript code. They're not just erased from the code. Okay? And we're not going to support that and JSX because well, that's not TypeScript the consequences if this proposal ends normal transportation of most of TypeScript and flow with real browser ESM we will be able to finally remove all tooling during there that's my hope. This will still be checked by thirdparty type checkers. Slow convergence of incompatible TypeScript and flow to the new syntax like the minor incompatibilities tooling will become much simpler. And other type systems, hopefully, and probably will be experimented with. But it will take time. It will take years. Not months, years. And I think it will be worth the wait. And thank you very much.