Goal

Reserve a space for static type syntax inside the ECMAScript language. JavaScript engines would treat type syntax as comments.

Before

ts
const message: string = "Hello, types"
console.log(message)
SyntaxError: Unexpected token ':'. const declared variable 'message' must have an initializer.
💥

Runs with tools, crashes in a browser

After

ts
const message: string = "Hello, types"
console.log(message)

Runs without tools, runs in a browser

The Types as Comments proposal aims to simplify working in a modern JavaScript codebases. With Types as Comments, developers can remove a build step from their apps, keeping TypeScript and Flow codebases aligned with JavaScript. This proposal does not precisely specify a type syntax, which provides innovative space for different type systems.

How the proposal works

ts
const message = "Hello, types"
 
/* Echo the message */
console.log(message)
Hello, types

Today, a JavaScript engine knows that a slash and a star (/*) indicates the start of a multi-line comment.

To the engine, this roughly means: "from this point in the code, keep reading characters and ignore them until you find a star with a slash right after */".

ts
const message: string = "Hello, types"
 
/* Echo the message */
console.log(message)
Hello, types

For the simplest case, the same idea could be applied to an engine which implements Type as Comments.

If the engine has just seen an variable like message and the next character is a colon (:), then treat the colon (:) and certain pieces of code after (': string') as a comment.

In this case, once an engine would hit the = charater, it would stop interpreting the code as comments and read the initializer of message.

To the JavaScript runtime, the runtime code would look like this:

ts
const message = "Hello, types"
 
 
console.log(message)
Hello, types

The underlying implementation would need to be a bit more complex than that. For example, to handle things like object type literals ({ id: string }) an engine would keep track of open and close braces.

The goal of the proposal is to provide a way to describe how to safely ignore type-like code inside the JavaScript language.

Who benefits?

JavaScript and TypeScript Users

Less need for source code transformation in modern JavaScript projects.

Cleaner and more powerful syntax than JSDoc comments.

Pasting typed code into consoles and REPLs just works.

Tool Makers

New experimental type systems can be built using the ignored syntax space.

Existing JavaScript tools can:

Engine Maintainers

Browser engines do not pay any type-checking cost at runtime.

Engine maintainers avoid the burden of parser upgrades as each type system evolves.

Frequently Asked Questions

What type syntax is proposed?

Type definitions on functions and variable declarations, import/exporting types, class field and methods, generics, type assertions, this parameters, and more.

Will JavaScript engines perform type-checking?

No, the goal is to let projects like TypeScript, Flow, and others provide the type system and check the code for type errors. JavaScript would only reserve a space in the JavaScript syntax for their type syntax to exist.

Will adding types slow down my JavaScript programs?

Like any new JavaScript feature, it would have performance trade-offs, and there is some amount of parsing that would be required; however the performance here should be relatively small as these types just act as comments.

In short, no.

Will this grow JavaScript bundle sizes?

It could, but if you are currently bundling and using type syntax, types are already being removed during that bundling process. Most existing tools could continue to strip away types, or delegate the task to optimizers/minifiers..

JavaScript files without a build-step would have more characters as a result of the types. This is the same trade-off as adding comments to files, and the same solutions apply (e.g. use a minifier).

How does this differ from JSDoc support?

Today JavaScript users can write JSDoc comments and have them checked by TypeScript or Closure Compiler.

The syntax for JSDoc support is more verbose than type syntax, and is less ergonomic for complex typing. With this proposal, you can get the JSDoc-like "works without build tools" experience without the constraints of JSDoc comments.

Does this proposal favor TypeScript?

The proposal favors TypeScript/Flow-like syntax inside JavaScript, and is strongly influenced by syntax which is common to both language extensions. The aim is to also leave the door open for new syntax extensions which haven't been anticipated yet.

That said, the language in this specification favours TypeScript as it is the most popular type-system, but nearly all of the proposed syntax spaces would benefit Flow users too.

Is there prior art?

Python similarly implements support for opt-in type-checking. However this proposal has a stronger stance of relying solely on type erasure. Ruby is quite similar too.

Will this slow down JavaScript's evolution?

JavaScript's backwards compatibility goals of never breaking old code means that this is something future JavaScript syntax improvements would need to take into account. It is unlikely to get in the way of most new syntax however, as it is a strictly specified gap in the language instead of code which runs.

How does this affect runtime error messaging?

At most, the only new errors that an engine could issue are SyntaxErrors. In some cases, the Types as Comments leaves a lot of room for invalid-looking syntax, but which is actually fine.

For example, this syntax would be expected to error in TypeScript or Flow, but would be accepted by a JavaScript engine.:

ts
const message: { abc=123 } = "Hello, types"

On the other hand, the Types as Comments proposal does have some expectations around type syntax, and ill-formatted types at the top level of an annotation might have issues.

js
const message: !!@@hello@@!! = "Hello, types"
SyntaxError

While there would be some restrictions on type syntax, the proposal leaves type space errors to the IDE and type checker to report when certain types are invalid.

I'm new, what are these terms?

JavaScript is a language which does not provide a way to declare the input/outputs of your code. For example, in JavaScript a variable can be set to a string, a number, an object, and more.

JavaScript extensions like TypeScript and Flow exist to add new syntax which have a way to state that "this variable should only ever hold a string."

The value in adding this syntax is that tooling can make better assumptions about how your code works, and let you know when something might go wrong. That tooling can live in your editor, or be a command-line app.

The process of verifying these assumptions is called type checking, and for JavaScript there are different type checkers with different trade-offs about how JavaScript code can be validated.

Prior to this proposal, you needed a tool like Babel or TypeScript to remove these types, but if this proposal is accepted, you won't need a build tool to remove them.

Removing this step can help simplify working in JavaScript projects to the point where you may not need any build tooling at all.

What does the grammar look like?

You can read the grammar spec here and notes for implementation inside the repo.

Frequently Asked Questions about TypeScript

Will all of TypeScript be supported by this proposal?

No, not all of today's TypeScript syntax would be supported by this proposal. This is similar to how Babel support for TypeScript does not support all of the existing TypeScript syntax.

For example enums, namespaces and class parameter properties are unlikely to be supported. In addition, specifying type arguments at function call-sites will require a slightly different syntax.

How would I convert my TypeScript codebase to JavaScript with Types as Comments?

It's possible that TypeScript would introduce an option to ensure that your code is compatible with Types as Comments.

Teams could incrementally migrate by addressing each reported error as necessary. When no new errors are reported, .ts file extensions could be replaced with .js and the migration would be done.

How does this differ from JSDoc support?

JSDoc solves the same problem as this proposal by putting the type information inside existing comments! Given the constraint of not being able to change the JavaScript language, this was the best compromise to introduce type-checking in plain JavaScript.

This proposal removes that constraint and changes the JavaScript language to permit syntax that can be used for types. This proposal allows you to have the cake ("It's just JavaScript") and eat it too ("I want to check the types"). You get all the benefits of TypeScript's JSDoc support, but without the awkward syntax.

Do I need to migrate?

No. TypeScript has backwards compatibility guarantees which means that you can continue to use `.ts` and `.tsx` files for TypeScript. Your code that works today will continue to work tomorrow.

In fact, given how new this proposal is, we strongly advise not to rewrite existing code as it would be premature.

Links

Motivations

How does this proposal improve the JavaScript ecosystem as a whole?

Supported Syntax

From types definitions to class properties, see all the proposed supported type-level syntax.

Frequently Asked Questions

How does this proposal relate to TypeScript or Flow support? and many other questions.