#### Current behavior The compiler today elides imports and exports that are types or **not** referenced in a value position in the body of the importing module. See spec sections [section 11.2.5](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#1125-commonjs-modules) and [section 11.2.6](https://github.com/Microsoft/TypeScript/blob/master/doc/spec.md#1126-amd-modules) for more details. This has allowed for using the same syntax to import types and/or namespaces the same way values are imported. This has been convenient but has caused some problems: 1. It has been consistently a source of confusion for TypeScript users (see issues: #2132, #2038, and #596). 2. It impedes single-file-transpilation (see #2499) as there is no way to know if a re-export (e.g. t in `export { t } from "mod"`) should be elided or not without looking at the whole program #### Proposed change ##### 1. Do not elide module imports even if they are only used in type position. Even if the import is not used, keep the module dependency (i.e. the require() call) to ensure any side effects are maintained. e.g.: ``` ts import { InterfaceFoo } from "foo"; import { ClassBar } from "bar"; var x: InterfaceFoo = new ClassBar(); ``` emits in ES6: ``` js import {} from "foo"; import { ClassBar } from "bar"; var x = new ClassBar(); ``` and ES5/commonjs: ``` js require("foo"); // import but do not capture var bar_1 = require("bar"); var x = new bar_1.ClassBar(); ``` ##### 2. Exports with no value side are always elided This is the existing behavior, an export to an interface or a non-instantiated module will be elided. e.g.: ``` ts interface I { } export { I }; // Elided along with the interface declaration ``` ##### 3. A `type` modifier is required for type-only imports and exports The `type` modifier will cause the import to alias the type side of the imported entity, and would indicate the intent for this import statement to be **always** elided. ``` ts import type { IFoo } from "mod1"; // import to "mod1" will be elided export type { IBar } from "mod2"; // similarly, export statement will be elided ``` Optionally `type` can be applied to specific named bindings in export and import declarations, which will result in eliding the import if _all_ its bindings are types. ``` ts import {type IFoo, type IBar} from "mod"; // import will be elided ``` **Errors**: - It is an error to use `type` on a value-only import/export (e.g. var declaration). - It is an error to import or re-export a type only name without a `type` modifier ``` ts import { Interface, Class, Enum } from "foo"; /// Error: import `Interface` does not have a value side /// and should be marked as type. export { type } from "bar"; /// Error: export `type` does not have a value side /// and should be marked as type. ``` - Similarly `default` exports must have a value side: ``` ts interface IFoo { } export default IFoo; /// Error: export default target must have a value. ``` #### Implications to `import =` / `export =` syntax The proposal only affects the new ES6-style import/export syntax. Existing elision rules for `import id = require("module")` and `export = id` are not changed.