A Proposal For Type Syntax in JavaScript

Daniel Rosenwasser

Today we’re excited to announce our support and collaboration on a new Stage 0 proposal to bring optional and erasable type syntax to JavaScript. Because this new syntax wouldn’t change how surrounding code runs, it would effectively act as comments. We think this has the potential to make TypeScript easier and faster to use for development at every scale. We’d like to talk about why we’re pursuing this, and how this proposal works at a high level.

Background

One recent trend our team has seen in the JavaScript world is a demand for faster iteration time and a reduction of build steps. In other words, "make it faster and make it simpler".

In some ways, this is already happening. Thanks to the success of evergreen browsers, developers can often avoid compiling newer versions of JavaScript to run on older runtimes. To some extent the same is also true of bundling – most browsers have built-in support for using modules, so bundling can be viewed as more of an optimization step than a necessity. This has increasingly been the case, so how is TypeScript keeping up?

If we go back to 2012 when TypeScript was first announced, the JavaScript world was drastically different! Some browsers shipped often, but not all. It was unclear how long we’d be stuck with ancient versions of Internet Explorer, and that led to tools like bundlers and compilers gaining adoption. TypeScript was able to really thrive in the age where adding a build step to JavaScript was a given – after all, if you need to compile your JavaScript anyway, why not compile away your types too? But if those trends we mentioned above continue, compiling away your types might be the only step between writing your TypeScript and running it, and we don’t want to be the ones standing in the way of a good developer experience!

In some ways, our JavaScript support bridges the gap here, and maybe you’ve seen this if you use an editor like Visual Studio or Visual Studio Code. Today, you can create a .js file in your editor and start sprinkling in types in the form of JSDoc comments.

/**
 * @param a {number}
 * @param b {number}
 */
function add(a, b) {
    return a + b;
}

Because these are just comments, they don’t change how your code runs at all – they’re just a form of documentation, but TypeScript uses them to give you a better JavaScript editing experience through things like code completions, refactorings, and more. You can even add type-checking by adding a // @ts-check comment to the top of your file, or running those files through the TypeScript compiler with checkJs. This feature makes it incredibly convenient to get some of the TypeScript experience without a build step, and you can use it for small scripts, basic web pages, server code in Node.js, etc.

Still, you’ll notice that this is a little verbose – we love how lightweight the inner-loop is for writing JavaScript, but we’re missing how convenient TypeScript makes it to just write types.

So what if we had both?

What if we could have something like TypeScript syntax which was totally ignored – sort of like comments – in JavaScript.

function add(a: number, b: number) {
    return a + b;
}

Our team believes there is a lot of potential here, and this month we’re hoping to bring it forward in a proposal to TC39, the ECMAScript standards committee!

How Would This Work?

When we’ve been asked "when are types coming to JavaScript?", we’ve had to hesitate to answer. Historically, the problem was that if you asked developers what they had in mind for types in JavaScript, you’d get many different answers. Some felt that types should be totally ignored, while others felt like they should have some meaning – possibly that they should enforce some sort of runtime validation, or that they should be introspectable, or that they should act as hints to the engine for optimization, and more! But in the last few years we’ve seen people converge more towards a design that works well with the direction TypeScript has moved towards – that types are totally ignored and erasable syntax at runtime. This convergence, alongside the broad use of TypeScript, made us feel more confident when several JavaScript and TypeScript developers outside of our core team approached us once more about a proposal called "types as comments".

The idea of this proposal is that JavaScript could carve out a set of syntax for types that engines would entirely ignore, but which tools like TypeScript, Flow, and others could use. This allows us to keep the things you love about TypeScript – its type-checking and editing experience – while removing the need for a build step in development.

So when it comes to writing and running code, a developer’s inner-loop would look a little different.

Today TypeScript goes through a process of compiling from .ts files to .js files, which then run in the browser. Our proposal is to simply have browsers run the input JavaScript code which would support type annotations.

Meanwhile, writing code and type-checking would stay the same. A developer could get instant type-checking feedback in an editor with TypeScript support, run TypeScript on the command line, and add TypeScript as part of their CI tasks. The biggest difference is that because we would not need a build step, we would dramatically lower the barrier to entry for JavaScript devs to experience the power of types and great tooling.

TypeScript and the VS family of editors can provide errors/diagnostics for both TypeScript and JavaScript files that use type annotations. This process is roughly what the tools do today.

To make this happen, JavaScript would minimally need to add syntax for things like type annotations on variables and functions, optionality modifiers (?) for parameters and class members, type declarations (interfaces and type aliases), and type assertion operators (as and !) – all of which would have no effect on how the surrounding code is run.

Things like visibility modifiers (e.g. public, private, and protected) might be in scope as well; however, enums, namespaces, and parameter properties would be out of scope for this proposal since they have observable runtime behavior. Those features could be proposed as separate ECMAScript features based on feedback, but our current goal is to support some large subset of TypeScript that we think could be a valuable addition to JavaScript.

With this carve out, we’ve left room for type-checkers to innovate in ways that require new syntax. That does mean that engines would happily run code with nonsensical types, but we believe type-checkers could (and should) be prescriptive and enforce stricter constraints than runtimes. Combined, this makes for a type syntax that could be customized across different checkers, or removable entirely if someone decides they’re not happy with TypeScript or any other type-checker.

What is this not?

It’s worth mentioning what this proposal isn’t.

Our team isn’t proposing putting TypeScript’s type-checking in every browser and JavaScript runtime – nor are we proposing any new type-checker to be put in the browser. We think doing that would cause problems for JavaScript and TypeScript users alike due to a range of issues, such as runtime performance, compatibility issues with existing TypeScript code, and the risk of halting innovation in the type-checking space.

Instead, we’re just proposing syntax that is compatible with and motivated by TypeScript, which could be used by any type-checker, but which would skipped over by JavaScript engines. We believe that this approach is the most promising for everyone, and would continue to allow TypeScript, Flow, and others to continue to innovate.

What’s next?

Given all this, we plan to present this proposal for Stage 1 at the upcoming March 2022 plenary meeting of TC39. We’ll be doing so with the support and guidance from our co-champions of this proposal, Rob Palmer at Bloomberg and Romulo Cintra at Igalia.

Reaching Stage 1 would mean that the standards committee believes that supporting type syntax is worth considering for ECMAScript. This isn’t a sure-fire thing – there are many valuable perspectives within the committee, and we do expect some amount of skepticism. A proposal like this will receive a lot of feedback and appropriate scrutiny. It may involve lots design changes along the way, and may take years to yield results.

But if we pull this all off, we have the chance to make one of the most impactful improvements to the world of JavaScript. We’re excited by that, and we hope you are too.

If you’re interested in hearing more about the specifics and current direction, head on over to the proposal repository. We look forward to hearing what you think!

And lastly, the TypeScript team and the champions group would like to recognize and extend our thanks to all those who worked on prior art, along with the contributors who reached out to help with types as comments, and especially Gil Tayar who helped spearhead it. We’re grateful to be part of such a passionate community!

54 comments

Discussion is closed. Login to edit/delete existing comments.

  • Rasmus Schultz 0

    This feature is for developers.

    This has no place in the end-user browser environment, where it would just make an excuse for developers to deploy more useless bloat.

    Addding this feature to DevTools or a Chrome extension would be perfectly feasible and fulfills the same purposes for developers, doesn’t it?

    And without muddying the JavaScript standard, or getting in the way of actually adding checked types or run-time optimizations to JavaScript in the future.

    • anonymous 0

      this comment has been deleted.

    • Stewart Anderson 0

      This is almost identical to what I was going to reply with. 100% spot on!

    • anonymous 0

      this comment has been deleted.

  • Jonathan Randy 0

    Don’t. Just don’t. Stop trying to ‘fix’ JavaScript. Well meaning, endless additions and patches to improve it just make it more of a bloated Frankenstein’s monster.

    Far better would be for browsers to adopt another modern alternate scripting language alongside JS – in the hope that most development could gradually move to that for developers who happen to not like JS.

    I love working with loosely typed languages… it’s just a different way of doing things that I think allows for far more immediate creativity and productivity than working within the straitjacket of Types. This opinion comes from working with many, many languages over 38 years of coding experience.

    (Admittedly, this is more of a comment against TS generally… but even the proposal discussed just sounds like yet more overblown tooling just to get around JS’s perceived inadequacies. This tool would be far better implemented as a browser extension for developers rather than as a extension to the language syntax itself)

    • Nigel White 0

      I agree. I’m in the same place. Many years of using strongly typed languages, but now I enjoy the flexibility of being able to use anything anywhere. You just have to be careful. And test a lot!

    • Brandon Faulkner 0

      This proposal (and Typescript in general) allows you to be as loosely-typed as you want. In theory, you can create a Typescript project and never use any types, and still enjoy some benefits of implicit typing like code completion and whatnot. Typescript is only as strict as the individual chooses to make it.. Outside of transpile times (which this proposal is looking to remove to some degree), I’ve never understood the argument “Typescript is bad because I like loosely typed languages”.. Typescript allows the best of both worlds.

      • Jonathan Randy 0

        I know this, and I understand this about TS (it’s the same thing TS developers always fire back). I actually run the TS language server for JS projects (you don’t have to use it on TS projects), as it is fast, and works nicely with the LSP stuff in SublimeText.

        The point is though that this proposal is merely to assist TS developers in the browser. It doesn’t need to be part of the JS language syntax at all, and should not add more additional bloat and complexity to JS engines just as a convenient crutch for TS developers during development (I can’t imagine you’d want to be sending all this additional junk in production mode). It belongs in a browser extension.

  • Tiep Nguyen 0

    please make it happen 🙌

  • liranCR 0

    I argue this proposal will make no difference compared to just using typescript itself.
    Even if the js parser could actively ignore type comments, why would we ever want to pass this data over the network? And assuming we don’t we’ll need a compiler to strip those out of the original code, create source maps for debugging and so on.

    You end up with the same workflow as typescript offers today

    • Juan Mendes 0

      That was my main question, why pass type information over the network when it’s going to be ignored?

  • Alex Sova 0

    I think, there is one more issue with the conceptual difference between TS entities and JS: in JS we have no primitives such as ‘string’, ‘boolean’ or ‘number’, we have only constructor objects like ‘String’, ‘Boolean’, etc… And we have some unknown runtime types. This will not completely break the idea, but it makes it inconsistent. Other words, you cannot mix JS and TS in their syntax because of their semantic differences, but if you want to avoid that – you will get standard comments…

  • Vikrant Bhat 0

    Excited for this!

  • Fredrik Söderström 0

    Comments are for humans, not for application code!

    If you want to add a type system to JavaScript, it needs to be properly added to the JavaScript syntax itself!

    Those using TypeScript can still transpiled down to this typed syntax.

    Right now TypeScript flavor has a huge hype, when I started coding web professionally jQuery flavor was as huge, then came CoffeScript. All these flavors has contributed hugely to the ECMAScript standard that I use everyday at work, and I’m grateful for all the ideas and contributions.

    Still TypeScript is not currently the standard that the browsers understand, for some project types it is great, for others less so. Regarding solid type systems, Rust, the JavaScript/TypeScript world can, and will probably in the coming years also learn a great deal from the Rust community in how they do error handling with Result/Option, structs over classes and more.

    Same as I have had great use of the recent additions for private class fields/methods `#method() {}` in my everyday work.

    I actually also think adding an optional type system for ECMAScript could have great benefits, I encourage all thoughts around it. But it cannot be defined as a convenient compilation target for TypeScript. The TypeScript community will always be able to transpile down the code to which ever syntax that becomes the final draft.

    Keep up the experimenting, take inspiration from TypeScript, Rust, Dart, Swift, but keep the comments for humans! 🙂

  • Guilherme Chaguri 0

    This would definitely be easier for simple projects that want typings without adding a compiler alongside. But I don’t see how this helps the TypeScript community.
    Developers would want to strip away all typings since they are only useful for development and not meant to do anything in runtime, so this removes the compilation step for simple projects but add a minification step for more complex projects.

    That being said, I don’t see how this is beneficial over comments or .d.ts files. I think it makes more sense to push browsers into supporting TS alongside JS than adding more bloat to JS.

  • Khushal Bhardwaj 0

    This is the second most exciting thing after Typescript, it’s just 🤯

    If there’s a wait list, I wanna join!

  • Jacob Stamm 0

    If JS containing this syntax makes it to the end-user’s browser, why wouldn’t the JS interpreter use it to speed up runtime optimizations?

    On the other hand, if zero difference in runtime behavior is being proposed, then it’s bloat that shouldn’t be delivered to the client in the first place. Developers are always going to have a build process which, at a minimum, minifies their JS. Tools like clean-css and cssnano already know how to strip comments. They can be modified to simply strip out this new type syntax. At which point, it shouldn’t be considered valid JS, but rather something new. Maybe “TypeScript Lite” with .tsl files? A zero-configuration version of TypeScript with this proposed subset of syntax. The limitation of this syntax would be the same as the current proposal: nothing with runtime implications. If it can be ignored by a JS runtime, then it can be stripped out by a minification tool using the same parsing algorithm.

    All-in-all, I think the current proposal gets the worst of both worlds. Either the syntax should have runtime behavior to justify the added bloat to the client, or it should get stripped out by a build tool.

Feedback usabilla icon