Today we’re happy to announce our release candidate for TypeScript 2.1! If you aren’t familiar with it, TypeScript is a language that adds optional static types to JavaScript, and brings new features from ES6 and later to whatever JavaScript runtime you’re using.
As usual you can get the RC through NuGet, or just by running
npm install -g typescript@rc
You can then easily use the RC release with Visual Studio Code or our Sublime Text Plugin.
You can also grab the TypeScript 2.1 installer for Visual Studio 2015 after getting Update 3.
While TypeScript 2.1 has a lot of great features coming up, we’d like to highlight how much more powerful TypeScript 2.1’s inference will be, as well as how much easier it will be to write asynchronous code in all runtimes.
Smarter Inference
TypeScript 2.1 now makes it easier to model scenarios where you might incrementally initialize variables. Since a lot of code is written like this in JavaScript, this makes it even easier to migrate existing codebases to TypeScript.
To understand better, let’s start off by talking about the any type.
Most of the time, if TypeScript can’t figure out the type of a variable, it will choose the any type to be as flexible as possible without troubling you. We often call this an implicit any (as opposed to an explicit one, where you would have written out the type).
let x; // implicitly 'any'
let y = []; // implicitly 'any[]'
let z: any; // explicitly 'any'.
From that point on, you can do anything you want with those values. For many people, that behavior was too loose, which is why the --noImplicitAny option will warn you whenever a type couldn’t be inferred.
With TypeScript 2.0 we built out a foundation of using control flow analysis to track the flow of types throughout your program. Because that analysis examines the assignments of every variable, we’ve leveraged that same foundation in TypeScript 2.1 to more deeply examine the type of any variable that seems like it’s destined for a better type. Instead of just choosing any, TypeScript will infer types based on what you end up assigning later on.
Let’s take the following example.
let x;
// We can still assign anything we want to 'x'.
x = () => 42;
// After that last assignment, TypeScript 2.1 knows that 'x'
// has the type '() => number', so it can be called.
x();
// But now we'll get an error that we can't add a number to a function!
console.log(x + 42);
// ~~~~~~
// error: Operator '+' cannot be applied to types '() => number' and 'number'.
// TypeScript still allows us to assign anything we want to 'x'.
x = "Hello world!";
// But now it also knows that now 'x' is a 'string'!
x.toLowerCase();
When it comes to assignments, TypeScript will still trust you and allow you to assign anything you want to x. However, for any other uses, the type checker will know better by climbing up and looking at whatever you’ve actually done with x.
The same sort of tracking is now also done for empty arrays! This means better completions:
let puppies = [];
puppies.push(new Puppy());
for (let pup of puppies) {
pup.bark();
// ^^^^ Get completion on 'bark'
}
And it also means that TypeScript can catch more obvious errors:
puppies[1] = new Kitty();
for (let pup of puppies) {
pup.bark();
// ~~~~ error: 'bark' does not exist on type 'Kitty'
}
The end result of all this is that you’ll see way fewer implicit any errors in the future, and get much better tooling support.
Downlevel Async Functions
Support for down-level asynchronous functions (or async/await) is coming in 2.1, and you can use it in today’s release candidate! async/await is a new feature in ECMAScript 2017 that allows users to write code around promises without needing to use callbacks. async functions can be written in a style that looks synchronous, but acts asynchronously, using the await keyword.
This feature was supported before TypeScript 2.1, but only when targeting ES6/ES2015. TypeScript 2.1 brings the capability to ES3 and ES5 runtimes, meaning you’ll be free to take advantage of it no matter what environment you’re using.
For example, let’s take the following function named delay, which returns a promise and waits for a certain amount of time before resolving:
function delay(milliseconds: number) {
return new Promise<void>(resolve => {
setTimeout(resolve, milliseconds);
});
}
Let’s try to work on a simple-sounding task. We want to write a program that prints "Hello", three dots, and then "World!".
function welcome() {
console.log("Hello");
for (let i = 0; i < 3; i++) {
console.log(".");
}
console.log("World!");
}
This turned out to be about as simple as it sounded.
Now let’s say we want to use our delay function to pause before each dot.
Without async/await, we’d have to write something like the following:
function dramaticWelcome() {
console.log("Hello");
(function loop(i){
if (i < 3) {
delay(500).then(() => {
console.log(".");
loop(i + 1);
});
}
else {
console.log("World!");
}
})(0);
}
This doesn’t look quite as simple any more! What about if we tried using async functions to make this code more readable?
First, we need to make sure our runtime has an ECMAScript-compliant Promise available globally. That might involve grabbing a polyfill for Promise, or relying on one that you might have in the runtime that you’re targeting. We also need to make sure that TypeScript knows Promise exists by setting our lib flag to something like "dom", "es2015" or "dom", "es2015.promise", "es5":
{
"compilerOptions": {
"lib": ["dom", "es2015.promise", "es5"]
}
}
Now we can rewrite our code to use async and await:
async function dramaticWelcome() {
console.log("Hello");
for (let i = 0; i < 3; i++) {
await delay(500);
console.log(".");
}
console.log("World!");
}
Notice how similar this is compared to our synchronous version! Despite its looks, this function is actually asynchronous, and won’t block other code from running in between each pause. In fact, the two versions of dramaticWelcome basically boil down to the same code, but with async & await, TypeScript does the heavy lifting for us.
Next Steps
TypeScript 2.1 RC has plenty of other features, and we’ll have even more coming for 2.1 proper. You can take a look at our roadmap to see what else is in store. We hope you give it a try and enjoy it!

Please add string-based enums!
The request is tracked by https://github.com/Microsoft/TypeScript/issues/3192. I would add an up-vote to it.
Mohamed – it would be great if that up-voting would be taken into the account.
String enums have the most thumbs-up (not counting ‘Love for TypeScript’) but it doesn’t seem like it’s being implemented.
Thanks for awesome TS
“The end result of all this is that you’ll see way fewer implicit any errors in the future”
I’m curious what this does entail exactly?
Your examples are still implicitly any (as any assignment is allowed), so I hope that the compiler will still emit an error at any usage site where the typing is not provably correct (by data flow) or whenever the variable may escape scope (e.g. is passed to another function, put into an array, into an object, captured by a lambda, …)
Is there an issue on github that covers this feature?
That is correct.
No implicit any warnings before were reported on declarations with no type annotations or initializers to infer the type from. With this change, no-implicit-any warnings will **only** be shown if the compiler could not infer the type of the variable through control flow. This applies to variables captured by inner functions as you noted. You will now also see the no-implicit-any warnings on the access location that the compiler could not verify the type at, in addition to the declaration location.
For instance:
“`ts
function f3() {
let x = []; // Error: Variable ‘x’ implicitly has type ‘any[]’ in some locations where its type cannot be determined.
x.push(5);
function g() {
x; // Error: Variable ‘x’ implicitly has an ‘any[]’ type.
}
}
“`
You can find more information about this in https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#implicit-any-errors and in https://github.com/Microsoft/TypeScript/pull/11263.
I’ve been waiting for downloevel async/await for well over a year. Excited to see it finally coming to fruition! Excellent work, TS team!
u guys are awesome
Oh gosh, look-a-head type inference is mind blowing. Can we say that TypeScript compiler is now the most advanced compiler available today? Thanks for all TS team for such beauty.
other languages have this feature.
two come directly to mind: nemerle, haxe
How can i use this new await syntax with class member methods?
class Test {
public delay(mill): Promise {/*…*/}
publilc await sayHello() {}
}
does not seem to work
oops, i seem to have a typo (:
it works properly written as:
publilc async sayHello() {}
Can we use the new async/await syntax when targeting es5?
i’m getting an error
“Async functions are only available when targeting ECMAScript 2015 or higher.”
If the “target” is “es6”, the “lib” should contain “es5”, but if your target is “es5”, only have “dom” and “es2015.promse” in the “lib” array. At least that makes it compiles and gives different output depending on es5 and es6, not sure if it actually works properly.
Compiling in VS code works fine, but as soon as I start editing after compiling, then it complains like the error you wrote. You could do typescript.validate.enable: false in settings, but that would also mean all other compile validation turns off. Hopefully someone else have a solution?
Same. Setting target to es5 with the libraries for es5 and es6.promise will compile except for the async/await compiler errors.
If I set target to es6 but use the libs for es5 etc., I get a lot more compiler errors whining about Symbol and Iterable and whatnot on every for..of involving arrays.
Why is async/await tied to ES6 as a whole rather than ES6.Promises specifically?
With control flow analysis in place can we expect to see tree shaking and dead code elimination. Is there an issue tracking that?
Hi David! I don’t think we’ll be pursuing that in the next release, but have an issue tracking it here: https://github.com/Microsoft/TypeScript/issues/8
Any chance there’s an installer that would work with the latest VS15 preview? I found this https://github.com/Microsoft/TypeScript/wiki/Dev-Mode-in-Visual-Studio but it mentions at the top that it doesn’t work with VS15. I guess that’s still true for this 2.1 RC?
This version of TypeScript will be part of the upcomming public release of VS “15”.
I hope you’re not planning on *only* shipping it in VS2017. Some of us won’t be upgrading right away.
Figured as much since I saw the “2017” article yesterday 🙂 Looking forward to it!
When will this be available for VS 2015?
Does this mean that implicitly defined variables will type juggle whenever you make re-assignments to them? I don’t want to be the grinch here, but this seems to go against the idea of *static* typing. It’s a behavior that I’d like to be able to turn off at least. If I’ll have to spend time figuring what a variable is when it can change its type every other two lines of code, I can live without this. Union type narrowing and user-guards are already complex enough without the types actually being able to change completely.
Big thumbs up though for async/await in ES5. I’ve been waiting a long time for that. Nice to see how fast the issues were closed between 2.0 and 2.1 milestones.
No VS 2015 install?
I’m writing Typescript for a system that *cannot* use a module loader and is restricted to ES5.
What Promise library would be best to use in this scenario? Everyone always recommends “es6-promise” but that library is in the form of a module, so I can’t use it.
If look here:
https://github.com/stefanpenner/es6-promise/blob/master/dist/es6-promise.js
you can see that it sets a global variable “ES6Promise” if there is no module system in place
Why not use WebPack to combine modules into one file, then the platform doesn’t need a module loader.
This is what everyone does in the browser.
Umm, no it is *not* what everyone does in the browser.
Async!!!!!! WOW!
Thank you for finally delivering this awesome feature!
It is a great article. You will surely like this also because it is a great stuff, yeah it’s give us lots of interest and pleasure. Their opportunities are so fantastic and working style so speedy.
Question; your use of the term “release candidate” is confusing. All my experience as a developer has taught me that if you haven’t finished all the features, it’s an alpha. If it’s feature-complete but needs to be tested and debugged, it’s a beta. If you think you’ve finished debugging and testing everything, and you’re looking to release it, it’s a release candidate. Given that what you’re releasing here is not in fact a release candidate, why confuse the issue?
YAY! can’t wait to try async & await for implementing my WebSocket ^ _ ^ y Thanks TS Team!
Absolutely love the async/await feature. Great work everybody.
It seems as if using async/await has some influence on the AngularJS digest cycle. Right now I have to call $scope.$digest(); in functions assigend to ng-click. Otherwise it takes about 400 ms before I can see updates in my UI. Not sure if this is a TypeScript async/await problem or a general problem using async.
I think this is a general problem using ES6 promise. If you use $q, it will take care of calling $scope.$digest()
H