TypeScript Version: 2.3.4
Code
// foo.ts
console.log(BAR);
import {BAR} from './bar';
// bar.ts
export const BAR = 'bar';
// tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"strict": true
}
}
Expected behavior:
TypeScript should reject foo.ts, because it is referring to BAR before it is initialized.
Actual behavior:
tsc raises no errors, and generates the following foo.js file:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
console.log(bar_1.BAR);
var bar_1 = require("./bar");
This fails at runtime with a TypeError.
Note that when I first encountered this issue, it was in code like this:
// ...
import BAR = innerNamespace.BAR;
// ...
import {innerNamespace} from './bar';
// ...
So it wasn't as obvious what was wrong.
ES6 imports are hoisted, so the code in foo.ts is valid and should run without errors. The problem here seems to be with the emitted code, which does not hoist the import. Not sure if changing the emit order would be problematic when emitting to other module systems like CommonJS.
FWIW I was curious what babel emits for foo.ts, and it correctly hoists the import, emitting the following JS code (see repl here):
'use strict';
var _bar = require('./bar');
console.log(_bar.BAR);
That's interesting, thanks for the info!
I guess changing the emit order would technically be a breaking change, since importing a module can have side effects. But I'm not sure how common this is in practice.
Ideally we would hoist the imports, but not change the emit order. This is what already happens for AMD and SystemJS.
I just found a similar surprise, and a place where TS should throw and doesn't:
function useA() {
// using `a` before it is declared surprisingly doesn't error in either TS or the
// DevTools console
console.log(a);
}
useA(); // This does error at run time and should error at compile time
const a = 1;
useA();
It looks like this issue is scheduled to be closed soon with https://github.com/microsoft/TypeScript/pull/39764 which tweaks import hoisting, but this fix will NOT fix the issue described by @appsforartists, which is the same bug I've experienced in my code.
Are there plans to fix this error?
Most helpful comment
Ideally we would hoist the imports, but not change the emit order. This is what already happens for AMD and SystemJS.