Today we are thrilled to announce the release of TypeScript 1.8. In the TypeScript 1.8 Beta release blog post, we highlighted some of the key features that are now available to TypeScript users – how JavaScript in TypeScript compilation provides a great way forward to start converting your JavaScript projects to TypeScript, improvements to JSX/TSX support, and our move to ChakraCore. This post supplements the above and details how TypeScript 1.8 provides full support for module augmentation, delivers a stronger type system with string literal types, and catches even more common bugs with smarter control flow analysis.
TypeScript 1.8 is available for Visual Studio 2015, Visual Studio 2013, NuGet (Compiler and MSBuild task), npm, and straight from the source.
Module Augmentation
TypeScript 1.8 allows users to design more modular libraries via module augmentation. This allows library authors to distribute their libraries in a piecemeal fashion. Previously, TypeScript made the assumption that modules wouldn’t change. With module augmentation, users have the ability to extend existing modules such that consumers can specify if they want to import the whole module or just a subset. This can be accomplished by simply adding an ambient module declaration and extending any existing types.
// scale.ts export class Scale { weightOnEarth(mass) {} } // advancedScale.ts import { Scale } from "./scale" ;
// create augmentation for Scale declare module "./scale" { // Augment Core class via interface merging interface Scale { weightOnMoon(mass); // not everyone needs moon weight } } Scale.prototype.weightOnMoon = /* insert implementation */; // consumer.ts import { Scale } from "./scale"; import "./advancedScale"; let scale: Scale; scale.weightOnMoon(10); // ok
String Literal Types
It is very common for JavaScript libraries to consume a string as a configuration parameter, and usually in such cases you want to restrict the possible strings to a certain set. Take the following example of a UI element that can specify an easing method:
declare class UIElement { animate(options: AnimationOptions): void; } interface AnimationOptions { deltaX: number; deltaY: number; easing: string; // Can be "ease-in", "ease-out", "ease-in-out" } new UIElement().animate({ deltaX: 100, deltaY: 100, easing: "out" }); // No error
With regular strings, there is no protection from this class of error. However, starting with TypeScript 1.8, strings in a type position will become string literal types. Only exact string matches are assignable to string literal types, and like any other type, they can be used in union types as well. So if we rewrite the AnimationOptions interface with string literal types, the API users now get type protection:
interface AnimationOptions { deltaX: number; deltaY: number; easing: "ease-in" | "ease-out" | "ease-in-out"; } // Error: Type '"out"' is not assignable to type '"ease-in" | "ease-out" | "ease-in-out"' new UIElement().animate({ deltaX: 100, deltaY: 100, easing: "out" });
Smarter Control Flow Analysis
It is common for complex logic that results in many branching code paths to produce hard to find bugs. TypeScript 1.8 delivers better control flow analysis to help you catch these at compile time.
Unreachable Code
JavaScript’s automatic semicolon insertion is fairly useful, but it can also lead to unwanted results at times. The example below, which actually returns undefined, highlights a common bug that is now detected by the TypeScript compiler.
function importantData() { return // Automatic semicolon insertion triggered with newline { x: "thing" // Error: Unreachable code detected. } }
If for whatever reason you are experiencing too many false positives, please let us know, but you can toggle this feature off with the --allowUnreachableCode flag.
Implicit Returns
In JavaScript, reaching the end of a function with no return statement results in implicitly returning undefined. Sometimes this is the intended behavior, but often times it can be a red flag for gaps in complex logic. Unlike unreachable code, this check is off by default. To get the added safety, just add the --noImplicitReturns flag.
function isPizza(food) { // Error: Not all code paths return a value. if (food === "pizza") { return true; } else if (food === "pie") { return true; } // implicitly returns `undefined` }
TypeScript 1.8 also includes control logic for unused labels and case clause fall-through. You can read more about those here.
So Much More!
If you want the deep dive on all the new features released with 1.8, check out our what’s new page. As always, we encourage you to weigh in on the future of TypeScript by browsing our existing issues, throwing us a pull request, or just hanging out with the team on gitter.

Wonderful. I’ve been using the 1.8 beta and the improvements are excellent. F-bounded polymorphism, synthetic default exports, reachability analysis, and “use strict” with –target es5 are some of favorites.
Wonderful news! I’m really pleased that tsconfig.json support in Visual Studio is now fully supported; that’s going to make a real difference. Keep up the great work.
Many thanks.
The example for “Module Augmentation” is weird.
Finally.
Great news!
I’ve been using 1.8 beta for a while and support for *.tsx files along with all the improvements and new features added really made difference on productivity and overall process. Distributing the TypeScript compiler and the MSBuild task as NuGet packages alongside with allowJs flag for consuming Javascript files alongside TypeScript files is something that will help in even larger community adoption.
I think that the line “Scale.prototype.advancedMethod = /* insert implementation */;” should be “Scale.prototype.weightOnMoon = /* insert implementation */;”. Otherwise the method would still be undefined
I believe your 2nd “Module Augmentation” example has a mistake. The line after the module definition reads:
Scale.prototype.advancedMethod = /* insert implementation */;
Shouldn’t this read
Scale.prototype.weightOnMoon = /* insert implementation */;
?
At first I was little bit confuse, but then I realized
declare module “./scale” {
interface Scale {
weightOnMoon(mass);
}
}
Scale.prototype.advancedMethod = /* … */;
should be
declare module “./scale” {
interface Scale {
weightOnMoon(mass);
}
}
Scale.prototype.weightOnMoon= /* weightOnMoon – same name as defined in nterface */;
I’m sorry, but I’m new in TypeWorld…
When are you publishing it to the VS Gallery?
Please continue to turn this into rocket science, wouldn’t it be faster to just emit javascript from c#. F-bounded poly rofl….
Great release!
Shouldn’t Scale.prototype.advancedMethod be Scale.prototype.weightOnMoon?
Unfortunately TS1.8 for VS2015 crash if you already have Update 2 CTP
Very glad to see string literals types, let/const in loops, F-bounded polymorphism, React function components, and will definitely be using –noImplicitReturns and –noFallthroughCasesInSwitch (suggestion: –maximumStrictness or similar that enables all such flags?)
(BTW In the example code is advancedMethod supposed to be weightOnMoon?)
Just a quick note to others that may come across this, don’t upgrade to this release if you’re on the CTP of VS 2015 Update 2. TypeScript broken all day for me yesterday and is only partially working now (not enough for actual work though) after some help from the team on GitHub. Several hours of uninstall / reinstall whilst watching TV last night and this morning.
See https://github.com/Microsoft/TypeScript/issues/7204 for the gory details 🙂
Relly like the control flow analysis, but please note: The download link for Visual Studio 2015 is pointing to the installer of the beta version of 1.8.1! There`s a newer link on the GitHub page for release 1.8.2 (https://github.com/Microsoft/TypeScript/releases), which will download the installer for 1.8.4…
Thanks for your hard work!
Just used module augmentation for the first time. Solves my use case perfectly 🙂
Keep up the great work!
Under Module Augmentation, is the following line correct?
Scale.prototype.advancedMethod = /* insert implementation */;
Should that really be “advancedMethod” or should it be “weightOnMoon”? If it is meant to be “advancedMethod” where does the definition of “weightOnMoon” come from (so that you can actually invoke it)?
It would be nice to have a post (or any doc) about how the nugets work.
I had a working project and when I installed the msbuild nuget I got a ton of compiler errors (Cannot Find Module..). None of it happened before installing the MsBuild nuget.
I would like the consistency of a NuGet for autobuilding, but I don’t really see how it works with the project….
Hey Stephen, did you ever get this working?
Nice features!
But instead of “String Literal Types” feature or in addition to it 🙂
I would prefer to have “literal enums”, so your example could be changed:
type Easing = enum {
IN = “ease-in”,
OUT = “ease-out”,
IN_OUT = “ease-in-out”
};
interface AnimationOptions {
deltaX: number;
deltaY: number;
easing: Easing; // Can be “ease-in”, “ease-out”, “ease-in-out”
}
new UIElement().animate({ deltaX: 100, deltaY: 100, easing: Easing.OUT }); // No error
you can mirror this behavior today by using both a type definition and an object literal:
type Easing = “ease-in” | “ease-out” | “ease-in-out”;
const Easing = {
IN: “ease-in” as “ease-in”,
OUT: “ease-out” as “ease-out”,
IN_OUT: “ease-in-out” as “ease-in-out”
};
You can following (and contribute) to conversation surrounding enums here: https://github.com/Microsoft/TypeScript/issues/1206
You can mimic that functionality with the following work around:
type Easing = “ease-in” | “ease-out” | “ease-in-out”;
const Easing = {
IN: “ease-in” as “ease-in”,
OUT: “ease-out” as “ease-out”,
IN_OUT: “ease-in-out” as “ease-in-out”
};
If you want to track (or contribute) to the current discussion on enums, check it out on GitHub: https://github.com/Microsoft/TypeScript/issues/1206
You can actually mimic that functionality with the following work around:
type Easing = “ease-in” | “ease-out” | “ease-in-out”;
const Easing = {
IN: “ease-in” as “ease-in”,
OUT: “ease-out” as “ease-out”,
IN_OUT: “ease-in-out” as “ease-in-out”
};
If you want to track (or contribute!) to the current discussion on enums, check it out on GitHub: https://github.com/Microsoft/TypeScript/issues/1206
Hi Kelly, thanks you so much pointing that!
From mentioned discussion I’ve learned more interesting option:
export enum Easing {
IN = “ease-in”,
OUT= “ease-out”,
IN_OUT= “ease-in-out”
}
See https://github.com/Microsoft/TypeScript/issues/1206#issuecomment-146521171
Note: your blog message editor doesn’t properly escape < and > enteties. The workaround in the prev example is to cast to type any each of the literal values: “ease-in”, …
Awesome work guys thanks!
Can anyone here explain something about the “Unreachable Code Detected”?
I have a few switch statements. All of them have a `default` clause. This default is purely there to provide the fact that an error happened. So I might throw a runtime error for example.
I get a bunch of compile errors saying my default is unreachable. Is this to be expected? It is like default can no longer be used in a switch.
Erase Erase…. lol. I always had a break after my default, but in the case of when you throw a new error, the break is unreachable. Delete the break not the default clause!
Erase Erase…. lol. I always had a break after my default, but in the case of when you throw a new error, the break is unreachable. Delete the break not the default clause!
Sorry for the delay in comments getting posted everyone. Our comment approval settings got reset.
Apologies for the “Scale.prototype.weightOnMoon” typo, and thanks to everyone who pointed it out! Fixed!