Non-nullable Types

null and undefined are two of the most common sources of bugs in JavaScript. Before TypeScript 2.0, null and undefined were in the domain of every type. That meant that if you had a function that took a string, you couldn’t be sure from the type alone of whether you actually had a string – you might actually have null.

In TypeScript 2.0, the new --strictNullChecks flag changes that. string just means string and number means number.

letfoo: string = null; // Error!

What if you wanted to make something nullable? Well we’ve brought two new types to the scene: null and undefined. As you might expect, null can only contain null, and undefined only contains undefined. They’re not totally useful on their own, but you can use them in a union type to describe whether something could be null/undefined.

letfoo: string | null = null; // Okay!

Because you might often know better than the type system, we’ve also introduced a postfix ! operator that takes null and undefined out of the type of any expression.

Control Flow Analysis for Types

TypeScript’s support for handling nullable types is possible thanks to changes in how types are tracked throughout the program. In 2.0, we’ve started using control flow analysis to better understand what a type has to be at a given location. For instance, consider this function.

Notice that after the assignment within the if block, TypeScript understood that it had to be dealing with an array of strings.
This sort of thing can catch issues early on and save you from spending time on debugging.

We owe a major thanks to Ivo Gabe de Wolff for his work and involvement in implementing this feature, which started out with his thesis project and grew into part of TypeScript itself.

Easier Module Declarations

Sometimes you want to just tell TypeScript that a module exists, and you might not care what its shape is. It used to be that you’d have to write something like this:

declaremodule"foo" {
varx: any;
export = x;
}

But that’s a hassle, so we made it easier and got rid of the boilerplate. In TypeScript 2.0 you can just write

declaremodule"foo";
declaremodule"bar";

When you’re ready to finally outline the shape of a module, you can come back to these declarations and define the structure you need.

What if you you depend on a package with lots of modules? Writing those out for each module might be a pain, but TypeScript 2.0 makes that easy too by allowing wildcards in these declarations!

declaremodule"foo/*";

Now you can import any path that starts with foo/ and TypeScript will assume it exists. You can take advantage of this if your module loader understands how to import based on a certain patterns too. For example:

declaremodule"*!text" {
constcontent: string;
export = content;
}

Now whenever you import a path ending with !text, TypeScript will understand that the import should be typed as a string.

import text = require("./hello.txt!text");
text.toLowerCase();

Next Steps

One feature you might be wondering about is support for async functions in ES3 & ES5. Originally, this was slated for the 2.0 release; however, to reasonably implement async/await, we needed to rewrite TypeScript’s emitter as a series of tree transformations. Doing so, while keeping TypeScript fast, has required a lot of work and attention to detail. While we feel confident in today’s implementation, confidence is no match for thorough testing, and more time is needed for async/awaitto stabilize. You can expect it in TypeScript 2.1, and if you’d like to track the progress, the pull request is currently open on GitHub.

TypeScript 2.0 is still packed with many useful new features, and we’ll be coming out with more details as time goes on. If you’re curious to hear more about what’s new, you can take a look at our wiki. In the coming weeks, a more stable release candidate will be coming out, with the final product landing not too far after.

We’d love to hear any feedback you have, either in the comments below or on GitHub. Happy hacking!

Join the conversation

Boo indeed. I was anticipating this release for async \ await for many reasons. This WAS on the roadmap for 1.6 from memory and we’re still waiting.

Maybe just delete the roadmap to stop pissing people off when you don’t deliver the major feature a lot of devs have been waiting for. Or at least retrospectively change the roadmap so we have nothing to base our arguments on.

Great news, the improved type checking will definitely help make our company’s codebase more robust!

Too bad ES5 generators didn’t make it in 2.0, but I understand that the new transformation-based emitter needs some more work. We already have a workaround in place by transpiling to ES6 and piping through Babel to get ES5 generators. Looks like we’ll keep that extra Babel step in our build chain for just a bit longer.

This is a common format for JS module loader to represent plugins. For instance requirejs, uses the the prefix to detonate the plugin name, so `text!./hello.txt` would be a request to load the file `./hello.txt` using the `text` loader plugin, which returns you the file contents as a string. similarly `json!./resource.json` returns you the result of calling `json.parse` on `./resource.json` as an object. you can find more details in: http://requirejs.org/docs/plugins.html

Improved control flow analysis is cool and useful. I’m not sure about the nullable types though. I’d preferred if you could declare it the other way round, e.g. let s: string not null; The way it is now, it can turn out hard to use the –strictNullChecks option in an existing code basis.

Can someone explain me, why is async/await so much desired ? Maybe I’m shortsighted and closed in my browser-side programming cage, but I can’t see it as enabler for some new continent of stunning possibilities. In fact I can imagine it only a bit simplifying AJAX requests…

Aysnc/await just cleans up a lot of asynchronous code instead of chaining callbacks or promises. It really boils down to cleaner syntax for the developer that reads more easily and IMO is easier to debug. You can target ES6 right now with typescript and see how they compile async/await into promises and generators, its pretty cool. This is a good example of the difference in syntax for the same behavior. AJAX is one example of an asynchronous process but there are more JS libraries taking advantage of Promises so I think this feature will become more important for the future of Javascript.

In C# for example the x?.y operator is the null conditional member access, and returns null if the left hand operand is null. This means the compiler introduces a null check for us in the code.

The new TypeScript x!.y operator seems to be slightly different – you are telling the compiler that you are sure x is not null, so just go ahead and make the call stifling the possible null compiler warning. The compiler is not introducing a null check for us.

WIN 10, VS /w update3, just installed TypeScript_Dev14full.
VS now highlighting “document.body” and “document.createElement” with red underline as if this properties does not exist on type Document.
In error list:
Error TS2339 Property ‘body’ does not exist on type ‘Document’.
Error TS2339 Property ‘createElement’ does not exist on type ‘Document’.
Error TS2339 Property ‘fillStyle’ does not exist on type ‘CanvasRenderingContext2D’.
Error TS2339 Property ‘fillRect’ does not exist on type ‘CanvasRenderingContext2D’.
…
Is it a bug, or should I install additional typings to fix this?

Deviating from the ES standard syntax-wise is a dangerous path. Maybe I can understand keywords like ‘readonly’ that are self-explanatory and have limited impact on the syntax, but the postfix operator crosses that line.

The whole argument for using TypeScript was that it built upon standard EcmaScript syntax. I can’t help but wonder what will happen when the postfix operator will be added to EcmaScript, but with a different meaning. How will TypeScript reconcile its special operator with the standard one?

Typescript is designed to be a super-set of the language, so it should be allowed and expected to *add* syntax when allowed. The postfix ! operator appears to just be a shorthand for type assertions which are already non-standard.

strs!.map(s => s.toLowerCase()); is the same as (strs as string[]).map(s => s.toLowerCase()) which is the same as (strs).map(s => s.toLowerCase()).

Actually, the ‘as’ syntax for type assertions is a good example of what happens when syntax collides. It was added to resolve the syntactic ambiguity between jsx and existing typescript syntax. I’d also hope that as typescript becomes more popular the ES standard process would take things like this into account when developing features.

===== PLEASE DO NOT DELETE COMMENTS!!!!!! =========
You may want to take a look at Scala.js (https://www.scala-js.org) which translates Scala to JavaScript (A safer way to build robust front-end web applications!). There is a comparison table which compares Scala.js against Typescript.

Look like demand for async (and disappointment by not implementing) is huge. So, if adding it is really few weeks away, as githubs states, then it will be wise to create intermediate version TS 2.05 which is 2.0 + async, than forcing devs for another months to wait, when rest of 2.1 features will be implemented, polished and tested.

TypeScript has nightly releases out of the master branch. Once the feature lands in the master branch, it will be available to every one to give it a try. We always love to get feedback for new features.

The key is to transpile Typescript to ES6 and then use Babel to go from ES6 to ES5. Sounds ugly but it’s not so bad; our webpack setup with awesome-typescript-loader actually makes it fairly easy due to webpack’s chainable loaders.

Webpack does help in that regard, but the performance is horrible. You have to parse each file 3 times (first pass = TS, second pass = Babel, third pass = Webpack) and because of loader abstraction there is no way to cache results between passes. Even with incremental compilation the performance degrades as you also need to generate source maps on each pass. It adds complexity to an already complicated build process and makes it harder to debug when something goes wrong either in the build process or with the generated code.

To all those complaining about the async/await delay, go take a look at https://github.com/Microsoft/TypeScript/pull/9175 and see some of the issues/discussions/blockers that are actually causing the delay. It’s taking time because they’re doing it properly.

ERROR in [default] /home/username/node_modules/@types/node/index.d.ts:110:12
Subsequent variable declarations must have the same type. Variable ‘Buffer’ must be of type ‘{ new (str: string, encoding?: string): Buffer; new (size: number): Buffer; new (array: Uint8Arra…’, but here has type ‘{ new (str: string, encoding?: string): Buffer; new (size: number): Buffer; new (array: Uint8Arra…’.