DEV Community

Cover image for This Microsoft proposal will prevent JavaScript from ever getting a type system
Kirill Shestakov
Kirill Shestakov

Posted on

This Microsoft proposal will prevent JavaScript from ever getting a type system

On Mar 9, 2022, Microsoft announced a proposal to add type syntax to the JavaScript language (originally proposal-types-as-comments; later renamed to proposal-type-annotations).

The stated intention of the proposal is to enable a large portion of TypeScript (and Flow) code to be runnable in the browsers natively, without requiring compilation or bundling. The proposed idea is for JavaScript engines to strip out the type syntax as if it were comments:

type Result = {
  a: number,
  b: number,
  sum: number
};
function sum(a: number, b: number): Result {
  const sum: number = a + b;
  return {
    a,
    b,
    sum
  };
}
Enter fullscreen mode Exit fullscreen mode

In the above example, any type information such as { a: number, ... }, : number, : Result, etc, will be ignored by JavaScript engines.

Why is this important?

Proposals are a way to make changes to the JavaScript language - a way to evolve it, to keep it modern, to solve common problems for the benefit of everyone using the language. Features like async-await and optional chaining started as proposals and have since become important parts of the language.

According to State of JS survey, one of the most greatly missed features in JavaScript is the ability to define and ensure static types:

Survey "What do you feel is currently missing from JavaScript" showing "Static Typing" as by far the most voted point

JavaScript community saw the benefits of static typing and prefers to work with statically typed code, and there are important reasons for it:

  • Type safety: ensuring that variables can only be used in ways that doesn't functionality
  • Clear intention: allowing you to express intention and code design with types
  • Better code cohesion: different parts of your code can communicate with each other in clearer ways
  • Documentation: external packages that are statically typed benefit from useful IDE suggestions

So, what's wrong?

It sounds great, right? We're going to get types in JavaScript! Well... actually, quite the opposite.

Famous Star Wars scene where an alien exclaims "It's a trap!"

The proposal will make this code valid, even though the types are wrong:

interface User {
  id: number,
  username: string,
  email: string,
}
const user: User = { name: 'bestGuy44' };
Enter fullscreen mode Exit fullscreen mode

Due to strong backwards compatibility guarantee provided by JavaScript, under this proposal, this code will always be valid JavaScript.

Because all type information is ignored as comments, that means all non-sensical code such as the following, will also become a fully proper JavaScript code:

type NonSenseType = {
  makes no sense but here we go
}
function fetchPeople(id: non sense): what ever {
  return "";
} 
Enter fullscreen mode Exit fullscreen mode

Because this code has to forever remain valid JavaScript and never fail, this means that any hypothetical future JavaScript type-checker cannot use this these type annotations to decide to accept or reject your code. The only possible way to introduce a type-checker to the language would be to add second type annotation syntax, which would be unreasonable if there is already syntax for that.

Why is this desirable for Microsoft?

Old Internet Explorer browser with msn.com open

TypeScript is led by Microsoft and is currently at an all time high in being used and loved by the community, and for good reasons. It would be a big shame, if someone came up with a great type system to rival TypeScript, proposed it and implemented it in JavaScript itself. If that were to happen, it would create quite a bit of a problem for the TypeScript project, if not rendering it useless.

Official type-checker that's incompatible with TypeScript is possibly the biggest threat to the TypeScript project. It is unclear whether getting rid of this threat is one of the intentions of the proposal, or any of its authors and champions, but it is what the proposal achieves along with the stated intention.

But TypeScript is already the best, so why not?

As someone who's been coding for many years in a variety languages, I love TypeScript, how it transformed JavaScript community and the ease of development in the language. It is also clear that TypeScript is far from being the best possible type system.

For one, it does not enforce strict typing.

// If something is declared as a string
let name: string;
// It may later be initialized as non string through "any"
name = 0 as any;
// or through a clever use of "as"
name = {} as unknown as string;
Enter fullscreen mode Exit fullscreen mode

TypeScript was designed to describe the existing JavaScript, not to make it more optimized or allow you to be in a better control of your memory layout. This is why it has types such as "number" instead of more optimized types like "int", "float", "i32", "f64", etc.

const age: u8 = 20; // not a thing
Enter fullscreen mode Exit fullscreen mode

TypeScript has more than one way to define types:

// 1
type Person = {
  name: string,
  age: number,
}

// 2
interface Person {
  name: string,
  age: number
}

// 3
class Person {
  name: string;
  age: number;
}
Enter fullscreen mode Exit fullscreen mode

This adds more confusion when learning TypeScript, and can become a reason for unnecessary debate in a workplace along the lines of tabs VS spaces.

In addition, TypeScript has a strong emphasis on Object-Oriented features of the language, adding things such as abstract classes, public / private / protected fields, which is not a surprise given the influence of C#. There is a plenty of debate within the community around the value of OOP, and, in particular, whether inheritance or composition should be preferred. It is my experience that inheritance, that TypeScript expands with aforementioned features, more often than not, leads to less clear and overall worse code than the analogous composition-based code.

Puzzle pieces that fit snugly, with one piece sitting on top of the puzzle

There are languages whose type systems provide many advantages that TypeScript does not. Rust, which has been considered to be the most beloved language, has a strict type system, with useful algebraic data types, allows optimized types and great control over the memory layout, is trait-based, and has no concept of classes and inheritance. It is natural for languages to get inspired by each other, and evolve to provide similar advantages to their own developers. It would be unwise to ignore languages like Rust, and not consider the advantages that stricter type systems give.

All that is to say that we can do better than TypeScript, and it is conceivable for a better type-checker to emerge and capture the hearts of developers. This proposal will make it much more difficult for such type-checker to emerge as an external tool like TypeScript and Flow, and impossible for it to emerge as a proposed standard.

Is it worth it?

Balance with 2 rocks on one end, and 3 on the other

Static typing provides important value that developers are yearning for. The proposal does not deliver this value and, instead, actively prevents the most desired feature developers are asking for from ever being proposed and considered as part of JavaScript standard.

The only people who will benefit from this proposal are people who both (1) are ok with using a subset of TypeScript or Flow (e.g. if you're using JSX or enums, you're not included) and (2) prefer not to compile or bundle their code. The extent of their benefit will be the ability to run code without compilation. Is it worth to receive this benefit, given that it will prevent JavaScript from ever getting a proper type system?

Top comments (0)