export interface IPromise { then(callback: (x: T) => IPromise): IPromise; } interface Promise { then(callback: (x: T) => Promise): Promise; } var x: IPromise; var x: Promise; interface IPromise2 { then(callback: (x: T) => IPromise2): IPromise2; } interface Promise2 { then(callback: (x: V) => Promise2): Promise2; // Uses V instead of T in callback's parameter } // Ok because T in this particular Promise2 is any, as are all the U and W references. // Also, the V of Promise2 happens to coincide with the T of IPromise2 (they are both string). var y: IPromise2; var y: Promise2;