Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does "all legal JavaScript is legal TypeScript" mean?

Tags:

I often hear people making statements like this

All JavaScript code is legal TypeScript code

or

TypeScript is a superset of JavaScript

But yet when I wrote some perfectly legal and reasonable JS code which has totally deterministic behavior:

var x = "hello".substr("w").toStrig * { m: 3 / true } + window + parseInt(Element).fzq; 

ECMAScript defines that x should have the value "NaN[object Window]undefined" which seems totally fine, but I got a bunch of errors from TypeScript! Isn't this statement "all JS is TS" a lie, then? What's the deal?

like image 554
Ryan Cavanaugh Avatar asked Jan 19 '17 19:01

Ryan Cavanaugh


People also ask

Is all TypeScript valid JavaScript?

Defining TypeScript TypeScript offers type annotations which provide optional, static type checking at compile time. Since it is a superset of JavaScript, all JavaScript is syntactically valid TypeScript.

Should I use TypeScript instead of JavaScript?

In terms of software development, TypeScript offers many advantages over JavaScript: Optional static typing. JavaScript is a dynamically typed language, which means that types are checked, and data type errors are only detected at runtime. This can be very dangerous and can create errors during production.

Is TypeScript safer than JavaScript?

TypeScript is not a perfect language by any means; it has flaws and can have security issues when used incorrectly. However, it is more secure than JavaScript, and when deciding between the two, TypeScript is what you should choose.

What is TypeScript and why use it instead of JavaScript?

TypeScript is a superset of the JavaScript language that has a single open-source compiler and is developed mainly by a single vendor: Microsoft. The goal of TypeScript is to help catch mistakes early through a type system and to make JavaScript development more efficient.


1 Answers

All JavaScript code is legal TypeScript code

Here's what this means:

  • TypeScript does not change the syntax of existing JavaScript
  • TypeScript does not change the behavior of existing JavaScript
  • TypeScript does consider some JS code to have type warnings, because that's the point

Syntax

TypeScript will successfully parse all legal JavaScript code. It will emit this code as-is (minus downleveling, e.g. ES6 arrow functions will be converted to the equivalent ES5 code if you are targeting ES5 or lower). You may ignore type warnings generated by this JS code if you like; type warnings will not stop TypeScript from writing the output .js file.

Behavior

TypeScript does not change the behavior of existing JavaScript code, even though many people wish it did! Any JS code run through the compiler will behave the same as if it were run directly*.

Type Warnings

TypeScript may issue type warnings on code that it considers incorrect.

What does incorrect mean? Note that JavaScript is deterministic. Unlike C++, for example, it is basically impossible to cause behavior which is "implementation-defined". JavaScript also very rarely throws exceptions; unlike other languages which might raise an exception when trying to multiply an object by a function, JS produces NaN. Accessing a property by a mispelled name will produce undefined instead of a runtime error (much to everyone's chagrin). So the bar for "incorrect" here is intentionally set more strictly than "crashes your computer" or "throws an exception".

Some code like this, for example, is all legal JavaScript that doesn't even throw an exception. TypeScript considers each of these lines to have an error; this is typically considered a positive by those who use it:

var x = { } + 3; // Error, can't add objects and numbers var y = "hello world".substr(1, 2, 3, 4, 5); // Error, too many parameters var z = { x: 1, x: 2 }; // Error, duplicate property 'x' var q = x[z]; // Error, indexing by an object doesn't really work... var u = "hi".lenth; // Error, no property 'lenth' on string 

But the spec!

A common counterargument goes like this

"The ECMAScript specification defines that Math.max coerces its arguments to a number, so it should be legal to call Math.max(someString, someOtherString)"

It is true that the ECMAScript specification explicitly defines the coercions that take place at runtime. However, this logic doesn't give us any actual insight. Taken at its face, this logic says that because all parameters are coerced to number at runtime, it should be legal to write

var x = Math.max("hello", window.setTimeout, { }); 

After all, this code does have defined behavior! But this misses the forest for the trees - it is plainly implausible that this code is correct for any reasonable definition of "correct". TypeScript's existence is predicated on the notion that some JavaScript code is not correct and you'd like to know about it.

The fact that the spec describes what happens is not instructive as to whether or not you're writing a correct program. A doctor can clearly describe what will happen to you if you eat a rock, but that doesn't mean rocks are food.

It's a category error to look at the ECMAScript specification, which is designed to specify behavior, and decide that it is in fact a normative document which describes correct code. If you want, you can run with the nihilistic theory that "anything the spec defines should be OK" and use a variant of TypeScript which never issues type warnings. This variant is widely available, and is called "JavaScript".


*: Exceptions to this rule are downlevelings which may have detectable differences due to limitations in the runtime, e.g. stack traces may be different

like image 57
Ryan Cavanaugh Avatar answered Sep 17 '22 11:09

Ryan Cavanaugh