diff --git a/when/when-tests.ts b/when/when-tests.ts
new file mode 100644
index 0000000000..35a97e01e8
--- /dev/null
+++ b/when/when-tests.ts
@@ -0,0 +1,184 @@
+///
+
+import when = require("when");
+
+class ForeignPromise {
+ constructor(private value: T) {
+ }
+
+ then(onFulfilled: (value: T) => U, onRejected?: (reason: any) => U) { return new ForeignPromise(onFulfilled(this.value)); }
+};
+
+var promise: when.Promise;
+var foreign = new ForeignPromise(1);
+var error = new Error("boom!");
+
+// TODO: with TypeScript 1.4 a lot of these functions should change to use PromiseOrValue
+// type PromiseOrValue = Promise | T;
+
+/* * * * * * *
+ * Core *
+ * * * * * * */
+
+/* when(x) */
+
+promise = when(1);
+promise = when(when(1));
+promise = when(foreign);
+
+/* when(x, f) */
+
+promise = when(1, val => val + val);
+promise = when(when(1), val => val + val);
+promise = when(foreign, val => val + val);
+
+/* when.try(f, ...args) */
+
+promise = when.attempt(() => 1);
+
+promise = when.attempt((a: number) => a + a, 1);
+promise = when.attempt((a: number) => a + a, when(1));
+
+promise = when.attempt((a: number, b: number) => a + b, 1, 2);
+promise = when.attempt((a: number, b: number) => a + b, 1, when(2));
+promise = when.attempt((a: number, b: number) => a + b, when(1), 2);
+promise = when.attempt((a: number, b: number) => a + b, when(1), when(2));
+
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, 1, 2, 3);
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, 1, when(2), 3);
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, when(1), 2, 3);
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, when(1), when(2), 3);
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, 1, 2, when(3));
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, 1, when(2), when(3));
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, when(1), 2, when(3));
+promise = when.attempt((a: number, b: number, c: number) => a + b + c, when(1), when(2), when(3));
+
+/* when.lift(f) */
+
+// TODO: This is the major issue with lack of union types, it's not possible to represent the return type of when.lift without them.
+
+var liftedFunc0: () => when.Promise = when.lift(() => 2);
+var liftedFunc1: (a: when.Promise) => when.Promise = when.lift((a: number) => a + a);
+var liftedFunc2: (a: when.Promise, b: when.Promise) => when.Promise = when.lift((a: number, b: number) => a + b);
+var liftedFunc3: (a: when.Promise, b: when.Promise, c: when.Promise) => when.Promise = when.lift((a: number, b: number, c: number) => a + b + c);
+
+/* when.join(...promises) */
+
+var joinedPromise: when.Promise = when.join(when(1), when(2), when(3));
+
+/* when.promise(resolver) */
+
+promise = when.promise(resolve => resolve(5));
+promise = when.promise((resolve, reject) => reject(error));
+
+/* when.resolve(x) */
+
+promise = when.resolve(1);
+promise = when.resolve(promise);
+promise = when.resolve(foreign);
+
+/* when.reject(error) */
+
+promise = when.reject(error);
+
+/* when.defer() */
+
+var deferred = when.defer();
+promise = deferred.promise;
+deferred.resolve(1);
+deferred.reject(error);
+
+/* * * * * * * *
+ * Promise *
+ * * * * * * * */
+
+/* promise.done(handleResult, handleError) */
+
+when(1).done((val: number) => console.log(val));
+when(1).done((val: number) => console.log(val), (err: any) => console.log(err));
+
+/* promise.then(onFulfilled) */
+
+promise = when(1).then((val: number) => val + val);
+promise = when(1).then((val: number) => when(val + val));
+
+promise = when(1).then((val: number) => val + val, (err: any) => 2);
+promise = when(1).then((val: number) => when(val + val), (err: any) => 2);
+
+/* promise.spread(onFulfilledArray) */
+
+// TODO: Work out how to do this...
+// promise = when([1, 2, 3]).spread((a: number, b: number) => a + b);
+// promise = when([1, 2, 3]).spread((a: number, b: number) => when(a + b));
+
+/* promise.fold(combine, promise2) */
+
+promise = when(1).fold((a: number, b: number) => a + b, 2);
+promise = when(1).fold((a: number, b: number) => a + b, when(2));
+
+promise = when(1).fold((a: number, b: number) => when(a + b), 2);
+promise = when(1).fold((a: number, b: number) => when(a + b), when(2));
+
+/* promise.catch(onRejected) */
+
+promise = when(1).catch((err: any) => 2);
+promise = when(1).catch((err: any) => when(2));
+
+promise = when(1).catch((err: any) => err.good, (err: any) => 2);
+promise = when(1).catch((err: any) => err.good, (err: any) => when(2));
+
+//TODO: error constructor predicate
+
+promise = when(1).otherwise((err: any) => 2);
+promise = when(1).otherwise((err: any) => when(2));
+
+promise = when(1).otherwise((err: any) => err.good, (err: any) => 2);
+promise = when(1).otherwise((err: any) => err.good, (err: any) => when(2));
+
+/* promise.finally(cleanup) */
+
+promise = when(1).finally(() => console.log('Cleaning up'));
+
+promise = when(1).ensure(() => console.log('Cleaning up'));
+
+/* promise.yield(x) */
+
+promise = when(true).yield(1);
+promise = when(true).yield(when(2));
+
+/* promise.else(x) */
+
+promise = when(1).else(2);
+promise = when(1).else(2);
+
+promise = when(1).orElse(2);
+promise = when(1).orElse(2);
+
+/* promise.tap(onFulfilledSideEffect) */
+
+promise = when(1).tap(val => console.log(val));
+
+/* promise.delay(milliseconds) */
+
+promise = when(1).delay(1000);
+
+/* promise.timeout(milliseconds, reason) */
+
+promise = when(1).timeout(1000);
+promise = when(1).timeout(1000, new Error('Too SLOW!'));
+
+/* promise.inspect() */
+
+var status: {
+ state: string;
+ value?: number;
+ reason?: any;
+};
+
+status = when(1).inspect()
+
+/* promise.with(thisArg) */
+
+promise = when(1).with(2);
+
+promise = when(1).withThis(2);
diff --git a/when/when.d.ts b/when/when.d.ts
index 475fb23a6e..1f71d9ebbd 100644
--- a/when/when.d.ts
+++ b/when/when.d.ts
@@ -3,7 +3,42 @@
// Definitions by: Derek Cicerone
// Definitions: https://github.com/borisyankov/DefinitelyTyped
+declare function When(value: When.Promise): When.Promise;
+declare function When(value: When.Thenable): When.Promise;
+declare function When(value: T): When.Promise;
+
+declare function When(value: When.Promise, transform: (val: T) => U): When.Promise;
+declare function When(value: When.Thenable, transform: (val: T) => U): When.Promise;
+declare function When(value: T, transform: (val: T) => U): When.Promise;
+
declare module When {
+ function attempt(f: () => T): Promise;
+
+ function attempt(f: (a: A) => T, a: Promise): Promise;
+ function attempt(f: (a: A) => T, a: A): Promise;
+
+ function attempt(f: (a: A, b: B) => T, a: Promise, b: Promise): Promise;
+ function attempt(f: (a: A, b: B) => T, a: Promise, b: B): Promise;
+ function attempt(f: (a: A, b: B) => T, a: A, b: Promise): Promise;
+ function attempt(f: (a: A, b: B) => T, a: A, b: B): Promise;
+
+ function attempt(f: (a: A, b: B, c: C) => T, a: Promise, b: Promise, c: Promise): Promise;
+ function attempt(f: (a: A, b: B, c: C) => T, a: Promise, b: Promise, c: C): Promise;
+ function attempt(f: (a: A, b: B, c: C) => T, a: Promise, b: B, c: Promise): Promise;
+ function attempt(f: (a: A, b: B, c: C) => T, a: Promise, b: B, c: C): Promise;
+ function attempt(f: (a: A, b: B, c: C) => T, a: A, b: Promise, c: Promise): Promise;
+ function attempt(f: (a: A, b: B, c: C) => T, a: A, b: Promise, c: C): Promise;
+ function attempt(f: (a: A, b: B, c: C) => T, a: A, b: B, c: Promise): Promise;
+ function attempt(f: (a: A, b: B, c: C) => T, a: A, b: B, c: C): Promise;
+
+ function lift(f: () => T): () => Promise;
+ function lift(f: (a: A) => T): (a: Promise) => Promise;
+ function lift(f: (a: A, b: B) => T): (a: Promise, b: Promise) => Promise;
+ function lift(f: (a: A, b: B, c: C) => T): (a: Promise, b: Promise, c: Promise) => Promise;
+
+ function promise(resolver: (resolve: (value: T) => void, reject: (reason: any) => void) => void): Promise;
+
+ function reject(reason: any): Promise;
/**
* Return a promise that will resolve only once all the supplied promisesOrValues
@@ -45,6 +80,7 @@ declare module When {
* - rejected with promiseOrValue's reason after it is rejected
*/
function resolve(promise: Promise): Promise;
+ function resolve(foreign: Thenable): Promise;
function resolve(value?: T): Promise;
interface Deferred {
@@ -56,28 +92,65 @@ declare module When {
}
interface Promise {
+ catch(onRejected?: (reason: any) => Promise): Promise;
+ catch(onRejected?: (reason: any) => U): Promise;
+
+ catch(filter: (reason: any) => boolean, onRejected?: (reason: any) => Promise): Promise;
+ catch(filter: (reason: any) => boolean, onRejected?: (reason: any) => U): Promise;
+
// Make sure you test any usage of these overloads, exceptionType must
// be a constructor with prototype set to an instance of Error.
catch(exceptionType: any, onRejected?: (reason: any) => Promise): Promise;
catch(exceptionType: any, onRejected?: (reason: any) => U): Promise;
- catch(filter: (reason: any) => boolean, onRejected?: (reason: any) => Promise): Promise;
- catch(filter: (reason: any) => boolean, onRejected?: (reason: any) => U): Promise;
-
- catch(onRejected?: (reason: any) => Promise): Promise;
- catch(onRejected?: (reason: any) => U): Promise;
+ finally(onFulfilledOrRejected: Function): Promise;
ensure(onFulfilledOrRejected: Function): Promise;
inspect(): Snapshot;
+ yield(value: Promise): Promise;
+ yield(value: U): Promise;
+
+ else(value: T): Promise;
+ orElse(value: T): Promise;
+
+ tap(onFulfilledSideEffect: (value: T) => void): Promise;
+
+ delay(milliseconds: number): Promise;
+
+ timeout(milliseconds: number, reason?: any): Promise;
+
+ with(thisArg: any): Promise;
+ withThis(thisArg: any): Promise;
+
otherwise(onRejected?: (reason: any) => Promise): Promise;
otherwise(onRejected?: (reason: any) => U): Promise;
+ otherwise(predicate: (reason: any) => boolean, onRejected?: (reason: any) => Promise): Promise;
+ otherwise(predicate: (reason: any) => boolean, onRejected?: (reason: any) => U): Promise;
+
+ // Make sure you test any usage of these overloads, exceptionType must
+ // be a constructor with prototype set to an instance of Error.
+ otherwise(exceptionType: any, onRejected?: (reason: any) => Promise): Promise;
+ otherwise(exceptionType: any, onRejected?: (reason: any) => U): Promise;
+
then(onFulfilled: (value: T) => Promise, onRejected?: (reason: any) => Promise, onProgress?: (update: any) => void): Promise;
then(onFulfilled: (value: T) => Promise, onRejected?: (reason: any) => U, onProgress?: (update: any) => void): Promise;
then(onFulfilled: (value: T) => U, onRejected?: (reason: any) => Promise, onProgress?: (update: any) => void): Promise;
then(onFulfilled: (value: T) => U, onRejected?: (reason: any) => U, onProgress?: (update: any) => void): Promise;
+
+ done(onFulfilled: (value: T) => void, onRejected?: (reason: any) => void): void;
+
+ fold(combine: (value1: T, value2: V) => Promise, value2: V): Promise;
+ fold(combine: (value1: T, value2: V) => Promise, value2: Promise): Promise;
+
+ fold(combine: (value1: T, value2: V) => U, value2: V): Promise;
+ fold(combine: (value1: T, value2: V) => U, value2: Promise): Promise;
+ }
+
+ interface Thenable {
+ then(onFulfilled: (value: T) => U, onRejected?: (reason: any) => U): Thenable;
}
interface Snapshot {