Issue 1:
A very nice addition to TypeScript's type system would be sum types in the spirit of ML-like languages. This is one of basic and simple programming constructs from functional programming which you really miss once you get used to it, but which seem to have a hard time being included in new modern languages (contrary to other features from functional programming such as first-class functions, structural types, generics).

I guess the most natural way to integrate sum types in the current language syntax would be to extend enum variants with extra parameters (similarly to what Rust does: http://doc.rust-lang.org/tutorial.html#enums ) and upgrade the switch statement to a more powerful structural pattern matching (although in a first step, simply discriminating on the toplevel variant and capturing its parameters would be already quite good).

This is quite different from other the proposal about "union types" (#14), which would mostly be useful to capture types in existing Javascript APIs. Sum types are rather used to describe algebraic data structures. They would be particularly useful for any kind of symbolic processing (including for implementing the TypeScript compiler).

Issue 2:
Many values or parameters in JavaScript can be of more than one type. For example, a function might take an object where one of the properties can be either a string or a number, but not a function.

Comments from Ron Buckton in https://typescript.codeplex.com/workitem/1364

I'd like to see type annotations provide some support for a type union. For example:

ES6 Promise

class Promise<T> {
// ...
static any<TResult>(...values: union { Promise<T>; T; }[]): Promise<T>;
static every<TResult>(...values: union { Promise<T>; T; }[]): Promise<T[]>;
static some<TResult>(...values: union { Promise<T>; T; }[]): Promise<T>;
then(resolve?: (value: T) => union { Promise<T>; T; }, reject?: (value: any) => union { Promise<T>; T; }): Promise<T>;
// ...
}

ES6 Loader

class Loader<T> {
// ...
normalize(name: string, referer?: Referer): union { string; { normalized: string; metadata?: any }; };
resolve(normalized: string, options?: { referer: Referer; metadata: any; }): union { string; { address: string; extra?: string[]; }; };
// ...
}

When static type checking is performed, it is possible to have some type issues when explicitly providing generic type arguments and having the wrong type chosen, but this exists today without supporting type unions.

The other open issue is what to do with a local that is a type union: should it act as an any, a type that contains all of the members of both (or all) types in the union, or a type that only contains the members that are the same in both (or all) types in the union.

An implicit or explicit type cast from a type union to one of the union types would pass without the need to perform an intermediate cast to , and an explicit type cast to a more specific type for any of the union types would likewise succeed without an intermediate cast.

Assignment to a local or field that is a type union would succeed as if it were either of the types (e.g. implicit or explicit type cast from a more specific type to a less specific type specified in the type union).

There is also a question on how to properly handle the intellisense for a symbol that uses a type union. It could either be represented as a number of overloads (similar to what would have to be typed today), or preserve the type union definition.

Union Declaration

Providing a typedef-like syntax for unions would also be useful to define a reusable definition:

union Ref<T> {
Promise<T>;
T;
}

This is roughly analogous to an interface that defines multiple call signatures:

// as an interface with call signatures...
interface ResolveCallback<T> {
(value: Promise<T>): void;
(value: T): void;
(): void;
}

// ...and as a union with function types
union ResolveCallback<T> {
(value: Promise<T>) => void;
(value: T) => void;
() => void;
}

Static Analysis

Adding type unions would require changes to the static type information to be supported. The primary goal of adding type unions is to help the compiler determine the best matching type for a call expression or return type expression. The following sections discuss various ways of handling static analysis of type unions.

Assigning to a Type Union

When assigning to an identifier that is annotated with a type union, passing a value as an argument to a function for a parameter that is a type union, returning a value from a function with a type union in its return type annotation, or type-casting a value to a type union, the type of the value being assigned or returned must be compatible (as either an exact match or a superset of type information) with one of the types defined in the type union.

For example:

// assign to variable
var value: union { Promise<number>; number; };
value = 1; // legal
value = Promise.resolve<number>(1); // legal
value = new Date(); // static error

// type-cast to union
declare var n: number;
declare var p: Promise<number>;
declare var a: any;
declare var d: Date;
<union { Promise<number>; number; }>n; // legal
<union { Promise<number>; number; }>p; // legal
<union { Promise<number>; number; }>a; // legal
<union { Promise<number>; number; }>d; // legal

// union in return value
function func(type: string): union { Promise<number>; number; } {
switch (type) {
case "number":
return 1; // legal

case "promise":
return Promise.resolve<number>(1); // legal

case "date":
return new Date(); // static error
}
}

// union in invocation expression
declare function func(promiseOrValue: union { Promise<number>; number; }): void;
declare var n: number;
declare var p: Promise<number>;
declare var a: any;
declare var d: Date;

func(n); // legal
func(p); // legal
func(a); // legal
func(d); // static error

Assigning from a Type Union

When assigning to another value from a type union or type-casting from a type union, the type of the value must be compatible (as either an exact match or a subset of type information) with one of the types in the union.

For example:

// assignment
declare var value: union { Promise<number>; number; };
var n: number;
var p: Promise<number>;
var a: any;
var d: Date;

n = value; // legal
p = value; // legal
a = value; // legal
d = value; // static error

// type-cast
<Promise<number>>value; // legal
<number>value; // legal
<any>value; // legal
<Date>value; // static error