"Safer mode" for TypeScript (or: the ability to avoid bad JS features)

Topics: Language Specification
Feb 27, 2013 at 4:08 PM
Edited Feb 27, 2013 at 4:12 PM
I know that TypeScript is designed to be a superset of JavaScript. However I do think there's a big demand for a JavaScript-like language that's considerably safer than what TypeScript currently offers.

I've made a list of some troubling things that TypeScript doesn't hide (I know it's intentional). The following code is valid TypeScript (no compiler errors):
b = 3; // var hoisting
var a = 'a';
var b = +a; // implicit conversion to string
var c = !a; // implicit conversion to bool
delete a;   // delete works on anything, not just object properties
var d = void a; // why do we need void?
var e = this.foo; // 'this'' has same horrible behavior as in javascript (and is always in context)
As a minimum, since JavaScript has "use strict", it's a pity that the tsc compiler can't optionally enforce the strict rules. It would be nice if tsc would even enforce stricter rules than "use strict", taking advantage of the type information.

(Note: JSLint can catch all of the above problems)

This may not have been an original TypeScript goal, but:
  1. It's relatively easy to add to the spec and implementation (the compiler should already have all the information needed to enforce safer code)
  2. This will give TypeScript a huge advantage over any other option currently available (and bring it on par with GWT, Fay, Elm, in terms of safety but with the key advantage of being easily used with regular JavaScript)
It's ridiculous that using "use strict" + JSLint alone is in a sense safer than TypeScript!

So, I'm suggesting to add an optional mode with every possible safety check, and where every violation results in a compiler error.

-- Noam Lewis
Feb 27, 2013 at 6:03 PM
I have a recommendation for you or any others that want to take on a new project.

The TypeScript compiler's parser and type checker are incredibly easy to use programmatically. You can easilybuild some type of checkstyle/PMD-like plugin system that looks at the AST nodes (w/ all the awesome symbol/type information in there too after type check) and do any checks you want. This would not be a hard project to develop (I have done it in a different way...heck I even overwrote the error emitter to avoid some bugs), but would take some smart architecting to get it right and keep it simple.

Then you can just write your own plugins. For example, here might be a plugin for forcing both sides of a concatenation to be a string if one side is:
class ImplicitStringOnConcatenation extends Plugin {
    onBinaryExpression(ast: TypeScript.BinaryExpression) {
        if (ast.nodeType != TypeScript.NodeType.Add) return;
        var isString = (check: TypeScript.AST) => { return check.type != null && check.type.isString(); };
        if (isString(ast.operand1) && !isString(ast.operand2)) this.violation(ast.operand2, "Implicit string conversion");
        else if (isString(ast.operand2) && !isString(ast.operand1)) this.violation(ast.operand1, "Implicit string conversion");
    }
}
Now, now sure how practical this specific plugin would be, but it shows how easy the TypeScript AST is to use. I don't have a need for the project, so I will not be taking it on myself.
Feb 28, 2013 at 1:29 PM
I fully agree with ncryptor.

"there's a big demand for a JavaScript-like language that's considerably safer than what TypeScript currently offers."

It is not just a demand, it is an absolute need. After all the years of progress made in language technology, we are condemned to use JavaScript!

The term SafeMode would be perfect, especially from a marketing stand point. Microsoft could have a free version of TypeScript for geeks and hobbyists and a paying one with SafeMode, generics and async for professionals who are on the clock. I bet most would be happy to pay. Imaging, delivering code without the fear of those insidious JavaScript bugs.

The need to accommodate pure JavaScript within a TypeScript's source code could be handled with an "Unsafe Region".

In answer to Cretz, TypeScript is like a potential lifesaver which may at very long last allow us to do our jobs efficiently without having to refashion our brains around a fully inadequate language. We do not want to write plugins. Microsoft has the best language people on the planet. We should let them do their thing.


Philippe Moransais
Feb 28, 2013 at 7:16 PM
cretz wrote:
I have a recommendation for you or any others that want to take on a new project.

The TypeScript compiler's parser and type checker are incredibly easy to use programmatically. You can easilybuild some type of checkstyle/PMD-like plugin system that looks at the AST nodes (w/ all the awesome symbol/type information in there too after type check) and do any checks you want. This would not be a hard project to develop (I have done it in a different way...heck I even overwrote the error emitter to avoid some bugs), but would take some smart architecting to get it right and keep it simple.
Although a plugin system can be useful, if a "safe mode" is not endorsed by the core TypeScript team the validations may totally break with every new version of the compiler.

Besides, safety checking is THE core feature missing for JavaScript development, not something that's "extra". It would be great if TypeScript offered a solution to this giant headache. It's not something that belongs in a plugin.
Mar 1, 2013 at 12:09 PM
Well question is if this is the job of TypeScript or the various plugins out there.

You can still use 'use strict' and you will catch the errors at the same place as before, so what tool chain you apply will be the one deciding when you catch it.
Also your implicit conversions won't fail under strict... You can get TypeScript to fail on them though...
var a = 'text';

var b = !a; //OK -> a=false
var c: string = !a; //ERROR
var d: bool = !a; //OK -> a=false

var x = +a; //OK -> x=NaN
var y: string = +a; //ERROR
var z: number = +a; //OK -> z=NaN
The most common problems with "this" also remains. That doesn't have much to do with "use strict" either.
TypeScript can help you a little bit though.
var div1 = document.createElement('div');
var div2 = document.createElement('div');
document.body.appendChild(div1);
document.body.appendChild(div2);
div1.innerText = "div1";
div2.innerText = "div2";

class t {
    private message = "Hello t";
    public hook(){
        window.onmousewheel = function(e) {
            div1.innerText = this.message;
        }
        
        window.onmousemove = (e: Event)=>{
            div2.innerText = this.message;
        };
    }
}
new t().hook();
So to me TypeScript isn't the right place to add these checks, instead it's a tooling thing. (Not sure how much of the above tools like JSLint etc captures?)

So at best the TypeScript compiler may adhere to 'use strict' and fail on things that will actually generate ReferenceErrors, SyntaxErrors etc under strict mode

There is a list at page 235: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf

Anyways that is my thoughts.
May 13, 2013 at 12:28 PM
Edited May 13, 2013 at 12:41 PM
Agree with PMoransais and ncryptor.

Productivity boosted:
  1. Safer codes though efficient means.
  2. Less test cases of covering non-deterministic behaviors of javascript
  3. Easier to do continuous integration.
So we have more reasons to stay with Visual Studio.

And apparently the roadmap at https://typescript.codeplex.com/wikipage?title=Roadmap&referringTitle=Home had cover most of what concerned PMoransais and ncryptor, say 0.9x to 1.x onward.

Keep the fingers crossed.
May 13, 2013 at 5:27 PM
This kind of request has been made before by me and others. For now, it seems the TypeScript team is focusing on getting the language specification to 1.0 and freezing the specs, which is a good goal. All of these checks can be enforced by the compiler later.

I agree with ncryptor for some of the complaints, and the thing about "use strict" is completely true! If you are compiling to ES5, that should just be there. But I think stuff like implicit bool conversion (!a) is something that is very useful once you get used to it. From here we see that it will be quite hard to get to a common ground on what should be allowed and what shoudn't, and this is why jslint/jshint have 200 options and no one agrees on what should be the standard.

For the "implicit/explicit this", I believe people have solved this for decades and its quite simple to just do implicit this, most successfull languages have it and its a proven concept with its proven workarounds, but I think that since TypeScript tries to keep old javascript compiling, this will be a dream for some time. I really like cofeescript @ sintax though, and there could be something similar for TypeScript at some point.

Now, as much as I'd love to get these features ASAP from the official TypeScript build, this is a free and open source project, and anyone can fork it anytime, add these features and get it out for testing.

I just hope that TypeScript start evolving to "something more" after 1.0, and not just keep following ES6. ES6 is planned for spec release in December this year, so at least there shouldn't be much more to catch up with.