Issue 1:
Various libraries have a concept of applying partial updates to an object. For example:

http://backbonejs.org/#Model-set

http://facebook.github.io/react/docs/component-api.html#setstate

Take the following example (to roughly mimic Backbone)

interface Person {
firstName: string
lastName: string
phoneNumber: string
}

var model = {
set: function(data: Person) {}
}

model.set({
phoneNumber: '405-555-1254'
})

In this case an error is thrown saying that properties are missing. One solution is to make all of the properties in the interface optional. However, that may not be desirable; I may actually want those properties to be required in other locations and only optional in this specific context. I would like to propose a feature where in a certain context a new type is created on-the-fly based on another type where all properties of the base type are optional. For example:

Person? => {
firstName?: string
lastName?: string
phoneNumber?: string
}

and therefore the following would work:

var model = {
set: function(data: Person?) {}
}

model.set({
phoneNumber: '405-555-1254'
})

I think this would also work particularly well in conjunction with my other suggestion #391

set: function(data: Person?!) {}

Where zero or more properties from Person will match but ONLY properties from Person will match.

Issue 2:
Async Functions

1 Async Functions

This is a spec proposal for the addition of Async Functions (also known as async..await) as a feature of TypeScript.

2 Use Cases

Async Functions allow TypeScript developers to author functions that are expected to invoke an asynchronous operation and await its result without blocking normal execution of the program. This accomplished through the use of an ES6-compatible Promise implementation, and transposition of the function body into a compatible form to resume execution when the awaited asynchronous operation completes.

This is based primarily on the Async Functions strawman proposal for ECMAScript, and C# 5.0 § 10.15 Async Functions.

3 Introduction

3.1 Syntax

An Async Function is a JavaScript Function, Parameterized Arrow Function, Method, or Get Accessor that has been prefixed with the async modifier. This modifier informs the compiler that function body transposition is required, and that the keyword await should be treated as a unary expression instead of an identifier. An Async Function must provide a return type annotation that points to a compatible Promise type. Return type inference can only be used if there is a globally defined, compatible Promise type.

Example:

var p: Promise<number> = /* ... */;
async function fn(): Promise<number> {
var i = await p; // suspend execution until 'p' is settled. 'i' has type "number"
return 1 + i;
}

var a = async (): Promise<number> => 1 + await p; // suspends execution.
var a = async () => 1 + await p; // suspends execution. return type is inferred as "Promise<number>" when compiling with --target ES6
var fe = async function(): Promise<number> {
var i = await p; // suspend execution until 'p' is settled. 'i' has type "number"
return 1 + i;
}

class C {
async m(): Promise<number> {
var i = await p; // suspend execution until 'p' is settled. 'i' has type "number"
return 1 + i;
}

async get p(): Promise<number> {
var i = await p; // suspend execution until 'p' is settled. 'i' has type "number"
return 1 + i;
}
}

3.2 Transformations

To support this feature, the compiler needs to make certain transformations to the function body of an Async Function. The type of transformations performed depends on whether the current compilation target is ES6, or ES5/ES3.

3.2.1 ES6 Transformations

During compilation of an Async Function when targeting ES6, the following transformations are applied:

The new function body consists of a single return statement whose expression is a new instance of the promise type supplied as the return type of the Async Function.

The original function body is enclosed in a Generator Function.

Any await expressions inside the original function body are transformed into a compatible yield expression.

As the precedence of yield is much lower than await, it may be necessary to enclose the yield expression in parenthesis if it is contained in the left-hand-side of a binary expression.

The Generator Function is executed and the resulting generator is passed as an argument to the __awaiter helper function.

The result of the __awaiter helper function is passed as an argument to the promise resolve callback.

Example:

// async.ts
var p0: Promise<number> = /* ... */;
var p1: Promise<number> = /* ... */;
async function fn() {
var i = await p0;
return await p1 + i;
}

// async.js
var __awaiter = /* ... */;

function fn() {
return new Promise(function (_resolve) {
_resolve(__awaiter(function* () {
var i = yield p0;
return (yield p1) + i;
}()));
});
}

3.2.2 ES5/ES3 Transformations

As ES5 and earlier do not support Generator Functions, a more complex transformation is required. To support this transformation, __generator helper function will be also emitted along with the __awaiter helper function, and a much more comprehensive set of transformations would be applied:

The new function body consists of a single return statement whose expression is a new instance of the promise type supplied as the return type of the Async Function.

The original function body is enclosed in a function expression with a single parameter that is passed as an argument to the __generator helper function.

All hoisted declarations (variable declarations and function declarations) in the original function body are extracted and added to the top of the new function body.

The original function body is rewritten into a series of case clauses in a switch statement.

Each statement in the function body that contains an await expression is rewritten into flattened set of instructions that are interpreted by the __generator helper function.

Temporary locals are generated to hold onto the values for partially-applied expressions to preserve side effects expected in the original source.

Logical binary expressions that contain an await expression are rewritten to preserve shortcutting.

Assignment expressions that contain an await are rewritten to store portions left-hand side of the assignment in temporary locals to preserve side effects.

Call expressions that contain an await in the argument list are rewritten to store the callee and this argument, and to instead call the call method of the callee.

New expressions that contain an await in the argument list are rewritten to preserve side effects.

Array literal expressions that contain an await in the element list are rewritten to preserve side effects.

Object literal expressions that contain an await in the element list are rewritten to preserve side effects.

try statements that contain an await in the try block, catch clause, or finally block are rewritten and tracked as a protected region by the __generator helper function.

The variable of a catch clause is renamed to a unique identifier and all instances of the symbol are renamed to preserve the block scope behavior of a catch variable.

break and continue statements whose target is a statement that contains an await expression are rewritten to return an instruction interpreted by the __generator helper function.

return statements are rewritten to return an instruction interpreted by the __generator helper function.

for..in statements that contain an await expression are rewritten to capture the enumerable keys of the expression into a temporary array, to allow the iteration to be resumed when control is returned to the function following an await expression.

Labeled statements that contain an await expression are rewritten.

await expressions are rewritten to return an instruction interpreted by the __generator helper function.

Example:

// async.ts
var p0: Promise<number> = /* ... */;
var p1: Promise<number> = /* ... */;
async function fn() {
var i = await p0;
return await p1 + i;
}

// async.js
var __awaiter = /* ... */;
var __generator = /* ... */;

function fn() {
var i;
return new Promise(function (_resolve) {
resolve(__awaiter(__generator(function (_state) {
switch (_state.label) {
case 0: return [3 /*yield*/, p0];
case 1:
i = _state.sent;
return [3 /*yield*/, p1];
case 2:
return [2 /*return*/, _state.sent + i];
}
}));
});
}

The following is an example of an async function that contains a try statement:

// async.ts
var p0: Promise<number> = /* ... */;
var p1: Promise<number> = /* ... */;
async function fn() {
try {
await p0;
}
catch (e) {
alert(e.message);
}
finally {
await p1;
}
}

// async.js
var __awaiter = /* ... */;
var __generator = /* .. */;

function fn() {
var i;
return new Promise(function (_resolve) {
resolve(__awaiter(__generator(function (_state) {
switch (_state.label) {
case 0:
_state.trys = [];
_state.label = 1;
case 1:
_state.trys.push([1, 3, 4, 6]);
return [3 /*yield*/, p0];
case 2:
return [5 /*break*/, 6];
case 3:
_a = _state.error;
alert(_a.message);
return [5 /*break*/, 6];
case 4:
return [3 /*yield*/, p1];
case 5:
return [6 /*endfinally*/];
case 6:
return [2 /*return*/];
}
}));
});
var _a;
}

As a result of these transformations, the JavaScript output for an Async Function can look quite different than the original source. When debugging the JavaScript output for an Async Function it would be advisable to use a Source Map generated using the --sourceMap option for the compiler.

4 Promise

Async Functions require a compatible Promise abstraction to operate properly. A compatible implementation implements the following interfaces, which are to be added to the core library declarations (lib.d.ts):

interface IPromiseConstructor<T> {
new (init: (resolve: (value: T | IPromise<T>) => void, reject: (reason: any) => void) => void): IPromise<T>;
}

interface IPromise<T> {
then<TResult>(onfulfilled: (value: T) => TResult | IPromise<TResult>, onrejected: (reason: any) => TResult | IPromise<TResult>): IPromise<TResult>;
}

The following libraries contain compatible Promise implementations:

ES6 - http://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-objects

WinJS - http://msdn.microsoft.com/en-us/library/windows/apps/br211867.aspx

Q - https://github.com/kriskowal/q

RSVP - https://github.com/tildeio/rsvp.js/

Bluebird - https://github.com/petkaantonov/bluebird

es6-promise - https://github.com/jakearchibald/es6-promise

lie - https://github.com/calvinmetcalf/lie

when - https://github.com/cujojs/when

asyncjs - https://github.com/rbuckton/asyncjs

A Grammar

A.1 Types

CallSignature [Await,AsyncParameter] :

TypeParameters opt ( ParameterList [?Await,?AsyncParameter]opt ) TypeAnnotation opt*

ParameterList_ [Await,AsyncParameter] *:_

RequiredParameterList [?Await]

OptionalParameterList [?Await,?AsyncParameter]

RestParameter [?Await]

RequiredParameterList [?Await] , OptionalParameterList [?Await,?AsyncParameter]

RequiredParameterList [?Await] , RestParameter [?Await]

OptionalParameterList [?Await,?AsyncParameter] , RestParameter [?Await]

RequiredParameterList [?Await] , OptionalParameterList [?Await,?AsyncParameter] , RestParameter [?Await]

RequiredParameterList [Await] :

RequiredParameter [?Await]

RequiredParameterList [?Await] , RequiredParameter [?Await]

RequiredParameter [Await] :

AccessibilityModifier opt BindingIdentifier [?Await] TypeAnnotation opt

Identifier : StringLiteral

OptionalParameterList [Await,AsyncParameter] :

OptionalParameter [?Await,?AsyncParameter]

OptionalParameterList [?Await,?AsyncParameter] , OptionalParameter [?Await,?AsyncParameter]

OptionalParameter [Await,AsyncParameter]:

[+AsyncParameter] AccessibilityModifier opt BindingIdentifier [Await] ? TypeAnnotation opt

[+AsyncParameter] AccessibilityModifier opt BindingIdentifier [Await] TypeAnnotation opt Initialiser [In]

[+AsyncParameter] BindingIdentifier [Await] ? : StringLiteral

[~AsyncParameter] AccessibilityModifier opt BindingIdentifier [?Await] ? TypeAnnotation opt

[~AsyncParameter] AccessibilityModifier opt BindingIdentifier [?Await] TypeAnnotation opt Initialiser [In,?Await]

[~AsyncParameter] BindingIdentifier [?Await] ? : StringLiteral

RestParameter [Await]:

... BindingIdentifier [?Await] TypeAnnotation opt

A.2 Expressions

BindingIdentifier [Await] : ( Modified )

Identifier but not await

[~Await] await

PropertyAssignment [Await] :

PropertyName : AssignmentExpression [?Await]

PropertyName CallSignature { FunctionBody }

GetAccessor

SetAccessor

async [no LineTerminator here] PropertyName CallSignature [Await,AsyncParameter] { FunctionBody [Await] }

GetAccessor :

get PropertyName ( ) TypeAnnotationopt { FunctionBody }

async [no LineTerminator here] get PropertyName ( ) TypeAnnotation opt { FunctionBody [Await] }

FunctionExpression [Await] : ( Modified )

function BindingIdentifier [?Await]opt CallSignature { FunctionBody }

async [no LineTerminator here] function BindingIdentifier [?Await]opt CallSignature [Await,AsyncParameter] { FunctionBody [Await] }

AssignmentExpression [Await] : ( Modified )

...

ArrowFunctionExpression [?Await]

ArrowFunctionExpression [Await] :

ArrowFormalParameters => Block [?Await]

ArrowFormalParameters => AssignmentExpression [?Await]

async [no LineTerminator here] CallSignature [Await,AsyncParameter] => Block [Await]

async [no LineTerminator here] CallSignature [Await,AsyncParameter] => AssignmentExpression [Await]

ArrowFormalParameters [Await] :

CallSignature

BindingIdentifier [?Await]

UnaryExpression [Await] : ( Modified )

...

< Type > UnaryExpression [?Await]

[+Await] await UnaryExpression [Await]

A.3 Functions

FunctionDeclaration [Await] : ( Modified )

FunctionOverloads [?Await]opt FunctionImplementation [?Await]

FunctionOverloads [Await] :

FunctionOverloads [?Await]opt FunctionOverload [?Await]

FunctionOverload [Await] :

function BindingIdentifier [?Await] CallSignature ;

FunctionImplementation [Await] :

function BindingIdentifier [?Await] CallSignature { FunctionBody }

async [no LineTerminator here] function BindingIdentifier [?Await] CallSignature [Await,AsyncParameter] { FunctionBody [Await] }

A.4 Classes

MemberFunctionImplementation:

AccessibilityModifieropt static opt PropertyName CallSignature { FunctionBody }

AccessibilityModifieropt static opt async [no LineTerminator here] PropertyName CallSignature [Await,AsyncParameter] { FunctionBody [Await] }

B Helper Functions

There are two helper functions that are used for Async Functions. The __awaiter helper function is used by both the ES6 as well as the ES5/ES3 transformations. The __generator helper function is used only by the ES5/ES3 transformation.

B.1 __awaiter helper function

var __awaiter = __awaiter || function (g) {
function n(r, t) {
while (true) {
if (r.done) return r.value;
if (r.value && typeof (t = r.value.then) === "function")
return t.call(r.value, function (v) { return n(g.next(v)) }, function (v) { return n(g["throw"](v)) });
r = g.next(r.value);
}
}
return n(g.next());
};

B.2 __generator helper function

var __generator = __generator || function (m) {
var d, i = [], f, g, s = { label: 0 }, y, b;
function n(c) {
if (f) throw new TypeError("Generator is already executing.");
switch (d && c[0]) {
case 0 /*next*/: return { value: void 0, done: true };
case 1 /*throw*/: throw c[1];
case 2 /*return*/: return { value: c[1], done: true };
}
while (true) {
f = false;
switch (!(g = s.trys && s.trys.length && s.trys[s.trys.length - 1]) && c[0]) {
case 1 /*throw*/: i.length = 0; d = true; throw c[1];
case 2 /*return*/: i.length = 0; d = true; return { value: c[1], done: true };
}
try {
if (y) {
f = true;
if (typeof (b = y[c[0]]) === "function") {
b = b.call(y, c[1]);
if (!b.done) return b;
c[0] = 0 /*next*/, c[1] = b.value;
}
y = undefined;
f = false;
}
switch (c[0]) {
case 0 /*next*/: s.sent = c[1]; break;
case 3 /*yield*/: s.label++; return { value: c[1], done: false };
case 4 /*yield**/: s.label++; y = c[1]; c[0] = 0 /*next*/; c[1] = void 0; continue;
case 6 /*endfinally*/: c = i.pop(); continue;
default:
if (c[0] === 1 /*throw*/ && s.label < g[1]) { s.error = c[1]; s.label = g[1]; break; }
if (c[0] === 5 /*break*/ && (!g || (c[1] >= g[0] && c[1] < g[3]))) { s.label = c[1]; break; }
s.trys.pop();
if (g[2]) { i.push(c); s.label = g[2]; break; }
continue;
}
f = true;
c = m(s);
} catch (e) {
y = void 0;
c[0] = 1 /*throw*/, c[1] = e;
}
}
}
return {
next: function (v) { return n([0 /*next*/, v]); },
1 /*throw*/: function (v) { return n([1 /*throw*/, v]); },
2 /*return*/: function (v) { return n([2 /*return*/, v]); },
};
};

B.2.1 _generator Arguments

argument
description

m
State machine function.

B.2.2 n Arguments

argument
description

c
The current instruction.

B.2.3 Variables

variable
description

d
A value indicating whether the generator is done executing.

i
A stack of instructions (see below) pending execution.

f
A value indicating whether the generator is executing, to prevent reentry (per ES6 spec).

g
The region at the top of the s.trys stack.

s
State information for the state machine function.

s.label
The label for the next instruction.

s.trys
An optional stack of protected regions for try..catch..finally blocks.

s.sent
A value sent to the generator when calling next.

s.error
An error caught by a catch clause.

y
The current inner generator to which to delegate generator instructions.

b
The method on n to execute for the current instruction. One of "next", "throw", or "return".

B.2.4 Instructions

instruction
args
description

0 /*next*/
0-1
Begin or resume processing with an optional sent value.

1 /*throw*/
1
Throw an exception at the current instruction. Executes any enclosing catch or finally blocks.

2 /*return*/
0-1
Returns a value from the current instruction. Executes any enclosing finally blocks.

3 /*yield*/
0-1
Suspends execution and yields an optional value to the caller of the generator.

4 /*yield**/
1
Delegates generator operations to the provided iterable (not needed for Async Functions, but provided for future support for down-level Generator Functions).

5 /*break*/
1
Jumps to a labeled instruction. Executes any enclosing finally blocks if the target is outside of the current protected region.

6 /*endfinally*/
0
Marks the end of a finally block so that the previous break, throw, or return instruction can be processed.

B.2.5 Protected Regions

A protected region marks the beginning and end of a try..catch or try..finally block. Protected regions are pushed onto the s.trys stack whenever a protected region is entered when executing the state machine. A protected region is defined using a quadruple in the following format:

field
required
description

0
yes
The start of a try block.

1
no
The start of a catch block.

2
no
The start of a finally block.

3
yes
The end of a try..catch..finally block.

B.3 __generator helper function (alternate)

var __generator = __generator || function (body) {
var done, instructions = [], stepping, region, state = { label: 0 }, delegated;
function step(instruction) {
if (stepping) throw new TypeError("Generator is already executing.");
if (done) {
switch (instruction[0]) {
case 0 /*next*/: return { value: void 0, done: true };
case 1 /*throw*/: throw instruction[1];
case 2 /*return*/: return { value: instruction[1], done: true };
}
}
while (true) {
stepping = false;
var region = state.trys && state.trys.length && state.trys[state.trys.length - 1];
if (region) {
switch (instruction[0]) {
case 1 /*throw*/:
instructions.length = 0;
done = true;
throw instruction[1];
case 2 /*return*/:
instructions.length = 0;
done = true;
return { value: instruction[1], done: true };
}
}
try {
if (delegated) {
stepping = true;
var callback = delegated[instruction[0]];
if (typeof callback === "function") {
var result = callback.call(delegated, instruction[1]);
if (!result.done) return result;
instruction[0] = 0 /*next*/;
instruction[1] = result.value;
}
delegated = undefined;
stepping = false;
}
switch (instruction[0]) {
case 3 /*yield*/:
state.label++;
return { value: instruction[1], done: false };
case 4 /*yield**/:
state.label++;
delegated = instruction[1];
instruction[0] = 0 /*next*/;
instruction[1] = void 0;
continue;
case 0 /*next*/:
state.sent = instruction[1];
break;
case 6 /*endfinally*/:
instruction = instructions.pop();
continue;
default:
if (instruction[0] === 5 /*break*/ && (!region || (instruction[1] >= region[0] && instruction[1] < region[3]))) {
state.label = instruction[1];
break;
}
if (instruction[0] === 1 /*throw*/ && state.label < region[1]) {
state.error = instruction[1];
state.label = region[1];
break;
}
state.trys.pop();
if (region[2]) {
instructions.push(instruction);
state.label = region[2];
break;
}
continue;
}
stepping = true;
instruction = body(state);
} catch (e) {
delegated = void 0;
instruction[0] = 1 /*throw*/, instruction[1] = e;
}
}
}
return {
next: function (v) { return step([0 /*next*/, v]); },
"throw": function (v) { return step([1 /*throw*/, v]); },
"return": function (v) { return step([2 /*return*/, v]); },
};
};