In TypeScript 1.9.0-dev.20160426 I tried:
import * as Promise from 'bluebird';
async function test() {
await Promise.delay(1000);
}
test();
The compiler reports:
error TS2529: Duplicate identifier 'Promise'. Compiler reserves name 'Promise' in top level scope of a module containing async functions.
Especially since this is purely for Node.js, I'd like to use Bluebird promises for their debuggability and import them as Promise instead of some other name.
Could I provide my own __awaiter or could the default one use the imported Promise?
See #6631 which describes the rationale for reserving the identifier Promise. The issue that prompted that PR has a lot of related discussion, starting around here. Personally I would have preferred another way of of solving the problem without reserving Promise since it breaks a lot of existing code such as yours (my reasons were stated here).
Thanks! I see that it's unlikely the current behavior would change then... Closing.
This is horrible but compiles and seems to work:
bluebird-shim.d.ts:
import * as Bluebird from 'bluebird';
export interface DummyConstructor extends Bluebird<any> {
new<T>(): Bluebird<T>;
all: any;
race: any;
}
declare global {
interface Promise<T> extends Bluebird<T> {}
interface PromiseConstructor extends DummyConstructor {}
}
Test code:
import * as Bluebird from 'bluebird';
Promise = Bluebird as any;
async function test() {
console.log('Waiting...');
await Promise.delay(1000);
console.log('Done!');
}
test();
Not sure if this is actually valid and whether redefining __awaiter is necessary. Will this break in ES7 (I'm guessing yes)?
Maybe I'll reopen this to have the above questions looked at, in case others run into the same issue.
Actually this simpler version compiles and runs fine:
Promise = require('bluebird');
async function test() {
await Promise.delay(1000);
}
test();
It simply assigns to the global Promise, avoiding the Duplicate identifier 'Promise' error. And bluebird's ambient Promise declarations already merge with the ES6 ones, so that things like delay are defined.
If you look at the emitted JavaScript, the builtin __awaiter function will then use this bluebird Promise constructor for the async function, despite #6631 which aimed to ensure that async functions always used the ES6 Promise in line with the ES spec.
Since a compliant runtime will always use ES6 Promises for async functions, even if the global Promise identifier has been re-assigned, the above code behaves differently to how it would run directly without downlevelling (e.g. in the Edge browser which natively supports async/await).
@yortus Thanks! I've been using typed-typings/npm-bluebird which seems to require the above shim.
I guess the conclusion is that there's several ways around the new stricter native ES6 promise requirement, and as long as the code is transpiled to ES6 instead of ES7, it should run the same on all platforms that support generators/yield. Targeting ES7 will break every possible hack.
Most helpful comment
Actually this simpler version compiles and runs fine:
It simply assigns to the global
Promise, avoiding theDuplicate identifier 'Promise'error. Andbluebird's ambientPromisedeclarations already merge with the ES6 ones, so that things likedelayare defined.If you look at the emitted JavaScript, the builtin
__awaiterfunction will then use this bluebirdPromiseconstructor for the async function, despite #6631 which aimed to ensure that async functions always used the ES6 Promise in line with the ES spec.Since a compliant runtime will always use ES6 Promises for async functions, even if the global
Promiseidentifier has been re-assigned, the above code behaves differently to how it would run directly without downlevelling (e.g. in the Edge browser which natively supports async/await).