Known breaking changes between 0.8 and 0.9

The 0.9.x series introduces breaking changes to help the language mature, align with the ECMAScript 5 standard and ECMAScript 6 draft recommendations, and general alignment of the compiler with the spec itself. While we try to limit the number of breaking changes, it’s important to make necessary changes now, before the language and tools reach 1.0.

Below is the list of currently known breaking changes.

Tightening of compiler to spec

Description: There was functionality allowed by the 0.8.3 compiler that was not explicitly allowed by the spec (eg, exploiting patterns of access modifiers to simulate ‘protected’).
Reason: We tightened the compiler to follow the spec more closely to avoid code that relies on a “loose” compiler implementation.

The type ‘bool’ is now ‘boolean’

Description: The name of the Boolean type was initially ‘bool’. During 0.9.0, ‘bool’ will be marked as deprecated, preferring instead the name ‘boolean’. As of 0.9.1, ‘bool’ will no longer be accepted.
Reason: The official name for the Boolean type in ECMAScript is ‘boolean’. The ‘bool’ type name is being changed to align with the standard, based on user feedback.

Default values and optional notation redundant

Description: We no longer allow both having an optional parameter with a default value. Now, you can use the optional parameter when it does not have a default value, otherwise set the default value.

function f(defValue = 3) { }
function f(optValue?:any) { }
Reason: Simplifying syntax to be clear which of the two the user intended.

Syntax of external module imports now uses 'require'

Description: Previously, an external module could be imported using the syntax "import Utils = module('utils')". This is now "import Utils = require('utils')". This is simple syntactic change.
Reason: The 'require' syntax aligns more closely with the code used in both AMD and CommonJS. With "export =" in TypeScript 0.9, this also makes clear that the result of an import may not be a module object.

The ‘module’ keyword no longer creates a type

Description: In 0.9.0, a clearer distinction is made between roles of namespaces, types, and values. Modules now contribute only to namespaces and values and will no longer contribute a type.
Reason: This simplification of the role of modules allow modules to now extend classes and functions more easily.

Introduction of generic types – Change to ‘Array’ type

Description: In 0.9.0, with the introduction of generics, the type of Array is now generic.
Reason: The Array type was less specialized before. Now, with the advent of generics, we can allow for a more precise typing of Array contents.

Introduction of generic types – Change to syntax parsing

Description: In 0.9.0, with the introduction of generics, a difference in how syntax is parsed was introduced. This may affect some forms of syntax that previously parsed as acceptable ES5. Specifically, the following example will no longer be parsed as a comma-delimited expression of two comparisons, but instead as an invocation of a generic function with two arguments:

myfun<x,y>(z)


To make this unambiguously an expression, use parentheses. For example:

(myfun < x), y > (z)


Reason: We follow the precedence set by other languages with regards to syntax for generics. Unfortunately, this does lead to ambiguities in a few cases.

Overload declarations must immediately precede implementation

Description: The 0.8.x series was more lax about what was allowed between overload declaration and its implementation
Reason: Tightening compiler to align with grammar

Indexers must have full type annotation now

Description:
interface a1 {
    [n: number];  //<-- was allowed in 0.8.x, now an error
}
interface a1 {
    [n: number]: string;  //<-- correctly specifies return type, valid in 0.8.x and 0.9.x
}

Reason: Tightening compiler to align with grammar

Statics must be fully-qualified

Description: Previously you could optionally not qualify a static member access when inside a static member definition
Reason: Just as classes require “this.”, statics will require “<Class name>.” to denote where the symbol comes from

No longer accept semicolon at the end of methods

Description:
class Todo extends Backbone.Model {
 
    // Default attributes for the todo.
    defaults() {
        return {
            content: "empty todo...",
            done: false
        }
    };
}

Reason: This may be from following the syntax more strictly in the 0.9.0 fidelity parser. We may soften this restriction in the future.

No longer accept "new number[]"

Description: In the 0.8.x series, we allowed some exceptions to the rule that an expression should follow 'new'. Here we allowed the type "number[]" to follow new.
Reason: This was accidentally allowed in the 0.8.x compiler. As part of the 0.9.x work, we're tightening the compiler, and in doing so no longer allow this.

'declare' now required for top level non-interface declarations in .d.ts files

Description: The 0.8.x series had a lot of lenience in the .d.ts file syntax. We want to tighten the syntax.
Reason: Loose syntax rules are confusing to users and lead to inconsistent .d.ts files.

The node.d.ts distributed with 0.8 is not compatible with 0.9

Description: The 'node.d.ts' distributed as part of 0.8 samples is no longer compatible. Use the up-to-date node.d.ts distributed with the 0.9 samples.
Reason: This is an effect of the "modules no longer create a type" simplification

String indexers constrain the types of members on the interface

Description: A string indexer with element type Foo is a constraint that all members of the interface will have types compatible with Foo. The only exception is that members implicitly inherited from Object which can be called on any object type continue to have the type provided in Object unless explicitly overridden. So this:
    export interface IEventListenerMap {
        hasOwnProperty(eventName: string): bool;
        [eventName: string]: IEventCallback[];
    }

Can be changed to this without changes to consumers of the interface (that is, they can keep using .hasOwnProperty).
    export interface IEventListenerMap {
        [eventName: string]: IEventCallback[];
    }

Reason: String indexers are unified with property lookup in 0.9, so that foo.bar and foo["bar"] behave the same.

Missing "no implicit any" style option

Description: There was an unsupported style option that would error if the compiler had to imply that the type of an expression was 'any'. This generally allowed users to tighten their codebases and only work with typed code.
Reason: This was temporarily removed in 0.9 as part of the refactoring work. We expect to add it back in 0.9.1.

Last edited Jun 24, 2013 at 6:17 PM by jonturner, version 15

Comments

jmoeller Mar 17 at 6:21 PM 
Regarding "Generic constraints no longer can reference parameters in the same parameter list": Any chance this will come back for 1.0? We are using this feature (which, if I understand it correctly, was already working?) quite extensively in our code base. While the pattern is probably not necessary for simple use cases, it is really useful to have when you are using patterns like mix in and is quite common when using generics as a design approach (instead of just employing it for typesafe collections)

jonturner Jan 8 at 11:23 PM 
@johnny_reilly - that's right, using that file lets you control order. On the commandline, you can also use the ///<reference path=...> compiler hints in your code to specify order.

johnny_reilly Dec 20, 2013 at 8:18 AM 
Hi Guys,

Just noticed the "Interfaces now merge with later interfaces having a higher priority" section under "Known breaking changes between 0.9.5 and 1.0".

It's not stated but I assume that this requires that enforce interface order using _references.ts? I don't know how script ordering is determined in the absence of _references.ts?

bmantuano Sep 5, 2013 at 5:54 PM 
Regarding the "Triple slash references must be listed first" breaking change, is there any plan to allow this moving forward?

From a code organization standpoint, it's much cleaner to keep the amd dependency tags inline with the actual require.js call like so:
var $ = require('jquery'); /// <amd-dependency path="jquery"/>

Rather than in multiple places as is now required:
/// <amd-dependency path="jquery"/>
// ...
// ...
var $ = require('jquery');

Mandating that they be split will be an ongoing maintenance problem.

andykscodeplex Aug 11, 2013 at 12:02 PM 
Could you please elaborate on: 'In Visual Studio, all TypeScript files in a project are considered to be referencing each other ...'

I took this to mean that I don't need to use "/// <reference path= ... " but clearly from the huge number of errors arising when I do this I have got this very wrong.

jonturner Jun 25, 2013 at 5:56 PM 
@jantrum - you can still describe the type that the module provides by hand using interfaces. We're also looking into a way of getting to the module's shape using a 'typeof' keyword in a type position, but this functionality isn't yet in 0.9

omidkrad Jun 3, 2013 at 4:42 PM 
You may want to add this as breaking change:
All tripple slash references should appear at top of the source file, otherwise they will be ignored.
https://typescript.codeplex.com/workitem/1091

Jantrim May 22, 2013 at 4:23 PM 
I am having issues with "modules no longer create a type". Maybe i am forgetting something. But using require http://requirejs.org/docs/api.html modules can be defined as a function, object. How should this be handled in 0.0.9,


in 0.0.8 we could do a

declare module "jquery" {
export function (string selector): jquery;
}

this now results in a compiler error TS1003: Identifier expected

Probably workitems issues https://typescript.codeplex.com/workitem/1029 and https://typescript.codeplex.com/workitem/1058 are related to this problem.

dlshryock May 20, 2013 at 2:52 PM 
@mihailik

Thanks, I'm actually aware that you can use lambdas like that, my hope was to get the ability to use functions like that as well.

Lambdas stored in a var cause a few problems in my opinion: they don't work for inheritance, they're mutable so they can be changed, they can have order of initialization problems, and they don't contain any sort of name property to identify them, which is bad for call stacks, and metaprogramming.

I really like the use of short functions that return their results immediately. For me, limiting yourself to a single computational result for a function is a great way to increase the modularity, and composability of your functions. It gets even better when you can partially apply functions to set up context, and then invoke them later with the rest of the arguments.

I've been using this technique along with the fact that you can extract the name of named functions as a type safe mapping layer between my client and server side code, as well as for handling routing page rendering in the client side. Without the named arrow functions, my code will unfortunately get much longer and more cumbersome.

I'm sure that these things are probably much more of a concern to me than they are to other people, but I figured I'd mention them anyways :D

mihailik May 18, 2013 at 8:50 AM 
Almost precisely that lambda is what's supported today:

var addOne = (n: number) => n+1;
var x: (a,b) => (c,d) => a+b+c+d

class A{
private _name:string;
greeting: () => "Hello, "+name;
}

dlshryock May 17, 2013 at 9:27 PM 
Is there any possibility of returning the ability to write functions like lambdas?

for example, it was to be possible to write the following prior to the 0.9 alpha:

function addOne(n:number) => n+1;

It probably doesn't seem very important for simple cases like the above, but it is extremely useful if you are doing function currying / partial application:

function x(a,b) => (c,d) => a+b+c+d;

would have to become:
function x(a,b){return function(c,d){ return a+b+c+d;} }

a fully curried function:
function x(a) => (b) => (c) => (d) => a+b+c+d;
would have to be:
function(a){return function(b){return function(c){return function(d){ return a+b+c+d; } } } }

It gets worse and worse the more you want to break argument lists apart.

And yes, I am using the arrow functions in real life production application, and would prefer them to be real named functions, not lambda variables :D

I would even like to go so far as to ask for their support as methods:

class A{
private _name:string;
greeting() => "Hello, "+name;
}

NN May 3, 2013 at 5:59 PM 
https://typescript.codeplex.com/releases/view/105503
Here you have installer and specification

marcocenz May 1, 2013 at 9:03 AM 
There is an updated version of the Language specifications?
The only one I've found is of October 2012 for Language version 0.8.0 :-(

omidkrad Apr 29, 2013 at 8:12 PM 
I love these improvements. Specially tightening the .d.ts definitions, it was becoming confusing.

jonturner Apr 23, 2013 at 6:14 PM 
Thanks, oisin. Fixed.

oisin Apr 23, 2013 at 2:11 PM 
You accidentally linked to a new page with your indexer example. It should be:

foo.bar and foo[ "bar" ]