-
Couldn't load subscription status.
- Fork 0
Breaking Changes
These changes list where implementation differs between versions as the spec and compiler are simplified and inconsistencies are corrected.
For breaking changes to the compiler/services API, please check the API Breaking Changes page.
In TypeScript 1.8 we've added a set of reachability checks to prevent certain categories of errors. Specifically
-
check if code is reachable (enabled by default, can be disabled via
allowUnreachableCodecompiler option)function test1() { return 1; return 2; // error here } function test2(x) { if (x) { return 1; } else { throw new Error("NYI") } var y = 1; // error here }
-
check if label is unused (enabled by default, can be disabled via
allowUnusedLabelscompiler option)l: // error will be reported - label `l` is unused while (true) { } (x) => { x:x } // error will be reported - label `x` is unused
-
check if all code paths in function with return type annotation return some value (disabled by default, can be enabled via
noImplicitReturnscompiler option)// error will be reported since function does not return anything explicitly when `x` is falsy. function test(x): number { if (x) return 10; }
-
check if control flow falls through cases in switch statement (disabled by default, can be enabled via
noFallthroughCasesInSwitchcompiler option). Note that cases without statements are not reported.switch(x) { // OK case 1: case 2: return 1; } switch(x) { case 1: if (y) return 1; case 2: return 2; }
If these errors are showing up in your code and you still think that scenario when they appear is legitimate you can suppress errors with compiler options.
Previously specifying both while using modules would result in an empty out file and no error.
Modules were always parsed in strict mode as per ES6, but for non-ES6 targets this was not respected in our emitted code. Now we ensure emitted modules are in strict mode. This shouldn't have any visible changes in most code as TS considers most strict mode errors as errors at compile time, but it means that some things which used to silently fail at runtime in your TS code, like assigning to NaN, will now loudly fail. You can reference the MDN Article on strict mode for a detailed list of the differences between strict mode and non-strict mode.
For full list of breaking changes see the breaking change issues.
In a class, the type of the value this will be inferred to the this type.
This means subsequent assignments from values the original type can fail.
Example:
class Fighter {
/** @returns the winner of the fight. */
fight(opponent: Fighter) {
let theVeryBest = this;
if (Math.rand() < 0.5) {
theVeryBest = opponent; // error
}
return theVeryBest
}
}Recommendations:
Add a type annotation:
class Fighter {
/** @returns the winner of the fight. */
fight(opponent: Fighter) {
let theVeryBest: Fighter = this;
if (Math.rand() < 0.5) {
theVeryBest = opponent; // no error
}
return theVeryBest
}
}The keywords abstract, public, protected and private are FutureReservedWords in ECMAScript 3 and are subject to automatic semicolon insertion. Previously, TypeScript did not insert semicolons when these keywords were on their own line. Now that this is fixed, abstract class D no longer correctly extends C in the following example, and instead declares a concrete method m and an additional property named abstract.
Note that async and declare already correctly did ASI.
Example:
abstract class C {
abstract m(): number;
}
abstract class D extends C {
abstract
m(): number;
}Recommendations:
Remove line breaks after keywords when defining class members. In general, avoid relying on automatic semicolon insertion.
For full list of breaking changes see the breaking change issues.
It is an error to specify properties in an object literal that were not specified on the target type, when assigned to a variable or passed for a parameter of a non-empty target type.
This new strictness can be disabled with the --suppressExcessPropertyErrors compiler option.
Example:
var x: { foo: number };
x = { foo: 1, baz: 2 }; // Error, excess property `baz`
var y: { foo: number, bar?: number };
y = { foo: 1, baz: 2 }; // Error, excess or misspelled property `baz`Recommendations:
To avoid the error, there are few remedies based on the situation you are looking into:
If the target type accepts additional properties, add an indexer:
var x: { foo: number, [x: string]: any };
x = { foo: 1, baz: 2 }; // OK, `baz` matched by index signatureIf the source types are a set of related types, explicitly specify them using union types instead of just specifying the base type.
let animalList: (Dog | Cat | Turkey)[] = [ // use union type instead of Animal
{name: "Milo", meow: true },
{name: "Pepper" , bark: true},
{name: "koko", gobble: true}
];Otherwise, explicitly cast to the target type to avoid the warning message:
interface Foo {
foo: number;
}
interface FooBar {
foo: number;
bar: number;
}
var y: Foo;
y = <FooBar>{ foo: 1, bar: 2 };Previously, for the files one.ts and two.ts, an import of "one" in two.ts would resolve to one.ts if they resided in the same directory.
In TypeScript 1.6, "one" is no longer equivalent to "./one" when compiling with CommonJS. Instead, it is searched as relative to an appropriate node_modules folder as would be resolved by runtimes such as Node.js. For details, see the issue that describes the resolution algorithm.
Example:
./one.ts
export function f() {
return 10;
}./two.ts
import { f as g } from "one";Recommendations:
Fix any non-relative import names that were unintended (strongly suggested).
./one.ts
export function f() {
return 10;
}./two.ts
import { f as g } from "./one";Set the --moduleResolution compiler option to classic.
Function and class default export declarations can no longer merge with entities intersecting in their meaning
Declaring an entity with the same name and in the same space as a default export declaration is now an error; for example,
export default function foo() {
}
namespace foo {
var x = 100;
}and
export default class Foo {
a: number;
}
interface Foo {
b: string;
}both cause an error.
However, in the following example, merging is allowed because the namespace does does not have a meaning in the value space:
export default class Foo {
}
namespace Foo {
}Recommendations:
Declare a local for your default export and use a separate export default statement as so:
class Foo {
a: number;
}
interface foo {
b: string;
}
export default Foo;For more details see the originating issue.
In accordance with the ES6 spec, module bodies are now parsed in strict mode. module bodies will behave as if "use strict" was defined at the top of their scope; this includes flagging the use of arguments and eval as variable or parameter names, use of future reserved words as variables or parameters, use of octal numeric literals, etc..
- MessageEvent and ProgressEvent constructors now expect arguments; see issue #4295 for more details.
- ImageData constructor now expects arguments; see issue #4220 for more details.
- File constructor now expects arguments; see issue #3999 for more details.
The compiler uses the new bulk-export variation of the _export function in the System module format that takes any object containing key value pairs (optionally an entire module object for export *) as arguments instead of key, value.
The module loader needs to be updated to v0.17.1 or higher.
Entry point of TypeScript npm package was moved from bin to lib to unblock scenarios when 'node_modules/typescript/bin/typescript.js' is served from IIS (by default bin is in the list of hidden segments so IIS will block access to this folder).
TypeScript 1.6 removes the preferGlobal flag from package.json. If you rely on this behaviour please use npm install -g typescript.
Starting with 1.6, decorators type checking is more accurate; the compiler will checks a decorator expression as a call expression with the decorated entity as a parameter. This can cause error to be reported that were not in previous releases.
For full list of breaking changes see the breaking change issues.
This is an alignment with the ES6 semantics of arrow functions. Previously arguments within an arrow function would bind to the arrow function arguments. As per ES6 spec draft 9.2.12, arrow functions do not have an arguments objects. In TypeScript 1.5, the use of arguments object in arrow functions will be flagged as an error to ensure your code ports to ES6 with no change in semantics.
Example:
function f() {
return () => arguments; // Error: The 'arguments' object cannot be referenced in an arrow function.
}Recommendations:
// 1. Use named rest args
function f() {
return (...args) => { args; }
}
// 2. Use function expressions instead
function f() {
return function(){ arguments; }
}For regular enums, pre 1.5, the compiler only inline constant members, and a member was only constant if its initializer was a literal. That resulted in inconsistent behavior depending on whether the enum value is initalized with a literal or an expression. Starting with Typescript 1.5 all non-const enum members are not inlined.
Example:
var x = E.a; // previously inlined as "var x = 1; /*E.a*/"
enum E {
a = 1
}Recommendation:
Add the const modifier to the enum declaration to ensure it is consistently inlined at all consumption sites.
For more details see issue #2183.
Prior to this release, contextual types did not flow through parenthesized expressions. This has forced explicit type casts, especially in cases where parentheses are required to make an expression parse.
In the examples below, m will have a contextual type, where previously it did not.
var x: SomeType = (n) => ((m) => q);
var y: SomeType = t ? (m => m.length) : undefined;
class C extends CBase<string> {
constructor() {
super({
method(m) { return m.length; }
});
}
}See issues #1425 and #920 for more details.
TypeScript 1.5 refreshes the DOM types in lib.d.ts. This is the first major refresh since TypeScript 1.0; many IE-specific definitions have been removed in favor of the standard DOM definitions. as well as adding missing types like Web Audio and touch events.
Workaround:
You can keep using older versions of the library with newer version of the compiler. You will need to include a local copy of a previous version in your project. Here is the last released version before this change (TypeScript 1.5-alpha).
Here is a list of changes:
- Property
selectionis removed from typeDocument - Property
clipboardDatais removed from typeWindow - Removed interface
MSEventAttachmentTarget - Properties
onresize,disabled,uniqueID,removeNode,fireEvent,currentStyle,runtimeStyleare removed from typeHTMLElement - Property
urlis removed from typeEvent - Properties
execScript,navigate,itemare removed from typeWindow - Properties
documentMode,parentWindow,createEventObjectare removed from typeDocument - Property
parentWindowis removed from typeHTMLDocument - Property
setCapturedoes not exist anywhere now - Property
releaseCapturedoes not exist anywhere now - Properties
setAttribute,styleFloat,pixelLeftare removed from typeCSSStyleDeclaration - Property
selectorTextis removed from typeCSSRule -
CSSStyleSheet.rulesis of typeCSSRuleListinstead ofMSCSSRuleList -
documentElementis of typeElementinstead ofHTMLElement -
Eventhas a new required propertyreturnValue -
Nodehas a new required propertybaseURI -
Elementhas a new required propertyclassList -
Locationhas a new required propertyorigin - Properties
MSPOINTER_TYPE_MOUSE,MSPOINTER_TYPE_TOUCHare removed from typeMSPointerEvent -
CSSStyleRulehas a new required propertyreadonly - Property
execUnsafeLocalFunctionis removed from typeMSApp - Global method
toStaticHTMLis removed -
HTMLCanvasElement.getContextnow returnsCanvasRenderingContext2D | WebGLRenderingContex - Removed extension types
Dataview,Weakmap,Map,Set -
XMLHttpRequest.sendhas two overloadssend(data?: Document): void;andsend(data?: String): void; -
window.orientationis of typestringinstead ofnumber - IE-specific
attachEventanddetachEventare removed fromWindow
Here is a list of libraries that are partly or entirely replaced by the added DOM types:
DefinitelyTyped/auth0/auth0.d.tsDefinitelyTyped/gamepad/gamepad.d.tsDefinitelyTyped/interactjs/interact.d.tsDefinitelyTyped/webaudioapi/waa.d.tsDefinitelyTyped/webcrypto/WebCrypto.d.ts
For more details, please see the full change.
In accordance with the ES6 spec, class bodies are now parsed in strict mode. Class bodies will behave as if "use strict" was defined at the top of their scope; this includes flagging the use of arguments and eval as variable or parameter names, use of future reserved words as variables or parameters, use of octal numeric literals, etc..
For full list of breaking changes see the breaking change issues.
See issue #868 for more details about breaking changes related to Union Types
Given multiple viable candidates from a Best Common Type computation we now choose an item (depending on the compiler's implementation) rather than the first item.
var a: { x: number; y?: number };
var b: { x: number; z?: number };
// was { x: number; z?: number; }[]
// now { x: number; y?: number; }[]
var bs = [b, a]; This can happen in a variety of circumstances. A shared set of required properties and a disjoint set of other properties (optional or otherwise), empty types, compatible signature types (including generic and non-generic signatures when type parameters are stamped out with any).
Recommendation Provide a type annotation if you need a specific type to be chosen
var bs: { x: number; y?: number; z?: number }[] = [b, a];Using different types for multiple arguments of type T is now an error, even with constraints involved:
declare function foo<T>(x: T, y:T): T;
var r = foo(1, ""); // r used to be {}, now this is an errorWith constraints:
interface Animal { x }
interface Giraffe extends Animal { y }
interface Elephant extends Animal { z }
function f<T extends Animal>(x: T, y: T): T { return undefined; }
var g: Giraffe;
var e: Elephant;
f(g, e);See https://github.com/Microsoft/TypeScript/pull/824#discussion_r18665727 for explanation.
Recommendations Specify an explicit type parameter if the mismatch was intentional:
var r = foo<{}>(1, ""); // Emulates 1.0 behavior
var r = foo<string|number>(1, ""); // Most useful
var r = foo<any>(1, ""); // Easiest
f<Animal>(g, e);or rewrite the function definition to specify that mismatches are OK:
declare function foo<T,U>(x: T, y:U): T|U;
function f<T extends Animal, U extends Animal>(x: T, y: U): T|U { return undefined; }You cannot use heterogeneous argument types anymore:
function makeArray<T>(...items: T[]): T[] { return items; }
var r = makeArray(1, ""); // used to return {}[], now an errorLikewise for new Array(...)
Recommendations Declare a back-compat signature if the 1.0 behavior was desired:
function makeArray<T>(...items: T[]): T[];
function makeArray(...items: {}[]): {}[];
function makeArray<T>(...items: T[]): T[] { return items; }var f10: <T>(x: T, b: () => (a: T) => void, y: T) => T;
var r9 = f10('', () => (a => a.foo), 1); // r9 was any, now this is an errorRecommendations Manually specify a type parameter
var r9 = f10<any>('', () => (a => a.foo), 1);ECMAScript 2015 Language Specification (ECMA-262 6th Edition) specifies that ClassDeclaration and ClassExpression are strict mode productions. Thus, additional restrictions will be applied when parsing a class declaration or class expression.
Examples:
class implements {} // Invalid: implements is a reserved word in strict mode
class C {
foo(arguments: any) { // Invalid: "arguments" is not allow as a function argument
var eval = 10; // Invalid: "eval" is not allowed as the left-hand-side expression
arguments = []; // Invalid: arguments object is immutable
}
}For complete list of strict mode restrictions, please see Annex C - The Strict Mode of ECMAScript of ECMA-262 6th Edition.
For full list of breaking changes see the breaking change issues.
Examples:
var ResultIsNumber17 = +(null + undefined);
// Operator '+' cannot be applied to types 'undefined' and 'undefined'.
var ResultIsNumber18 = +(null + null);
// Operator '+' cannot be applied to types 'null' and 'null'.
var ResultIsNumber19 = +(undefined + undefined);
// Operator '+' cannot be applied to types 'undefined' and 'undefined'.Similarly, using null and undefined directly as objects that have methods now is an error
Examples:
null.toBAZ();
undefined.toBAZ();TypeScript Language Basics
- Basic Types
- Interfaces
- Classes
- Namespaces and Modules
- Functions
- Generics
- Common Errors
- Integrating with Build Tools
- Compiler Options
- tsconfig.json
TypeScript Language Advanced
- Mixins
- Declaration Merging
- Type Inference
- Type Compatibility
- JSX
- Writing Definition Files
- Typings for NPM packages
News
TypeScript Contributors
- Contributing to TypeScript
- TypeScript Design Goals
- Coding Guidelines
- Spec conformance testing
- Useful Links for TypeScript Issue Management
- Writing Good Design Proposals
- Compiler Internals
Building Tools for TypeScript
- Architectural Overview
- Using the Compiler API
- Using the Language Service API
- Dev Mode in Visual Studio
FAQs