-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Description
The following code used to work in TS <= 1.0.3, but stopped working in TS 1.1.
interface Promise<T> {
/* ... */
}
interface Deferred<T> {
resolve: (value: T) => void;
reject: (error: Error) => void;
promise: Promise<T>;
}
interface VoidDeferred extends Deferred<void> {
resolve: (value?: void) => void;
}
function makeDeferred<T extends void>(): VoidDeferred;
function makeDeferred<T>(): Deferred<T>;
function makeDeferred<T>(): Deferred<T> {
// Dummy code
return {
resolve: function () { },
reject: function () { },
promise: null
};
}
var normalDeferred = makeDeferred<number>(); // this is line 26
normalDeferred.resolve(3);
var voidDeferred = makeDeferred<void>();
voidDeferred.resolve(); // Note: no need to pass an 'undefined' valueThe idea is that the T extends void overload of makeDeferred() returns a VoidDeferred, on which I can call resolve() without an argument. For non-void Deferred's, I do have to pass an argument to resolve().
When running it against the latest master, I get the following:
$ node ../TypeScript/built/local/tsc.js -m commonjs promise.ts
promise.ts(26,35): error TS2344: Type 'number' does not satisfy the constraint 'void'.
promise.ts(27,24): error TS2345: Argument of type 'number' is not assignable to parameter of type 'void'.
Apparently, it's trying to match 'number' to the 'void' type, which fails, but it doesn't try to use the more generic overload that follows (as it did in 1.0.3).
Changing the order of the overloads doesn't help, as the returned type then becomes a 'normal' Deferred (not a VoidDeferred), which requires passing an argument to resolve(), e.g. resolve(undefined).
Is there a better way of doing this?
Ideally even without having that VoidDeferred type?
I'm thinking of something like a 'specialization' of the interface just when T happens to be void, or maybe even that the compiler allows ommitting the argument if its type is void?