Skip to content

Import assignment does not emit import statement in ESNEXT #19500

Closed

Description

@janv

TypeScript Version: 2.7.0-dev.201xxxxx

Contrary to the documentation (https://www.typescriptlang.org/docs/handbook/modules.html), using import assignment when targeting ES2015/ES6/ESNEXT does NOT emit import statements in the generated JS.

Code

This is my input file:

import m = require('m')
m('123')

$ tsc -t ESNEXT index

Expected behavior:

import * as m from "m"
m('123')

As described by the documentation

Actual behavior:

m('123')

See also this playground (this is 2.4.2, but I tested locally with @latest)

The import is completely omitted


Background info: I am depending on JS libraries which module.exports = someFunction and have the matching declaration file. All this feeds into webpack, which could take care of the module compatibility issues later.

But the import statement is just omitted completely

Activity

  1. mhegazy commented on Oct 26, 2017

    @mhegazy
    Contributor
    c:\test\19500>type a.ts
    import m = require('m')
    m('123')
    
    c:\test\19500>tsc --v
    Version 2.7.0-dev.20171025
    
    c:\test\19500>tsc  -t ESNEXT a.ts
    a.ts(1,1): error TS1202: Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead.
    a.ts(1,20): error TS2307: Cannot find module 'm'.

    The relevant part is the error message Import assignment cannot be used when targeting ECMAScript modules. Consider using 'error TS1202: import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead.

    The behavior of require("m") is not the same as import * as m from "m", so it is not clear that there is even a way to transpile this correctly all the time.

  2. janv commented on Oct 26, 2017

    @janv
    Author

    You are correct about the error, and I can kinda understand the reasoning here. But I still see two/three issues:

    First, the documentation clearly (or am I misunderstanding something there?) describes a different behavior.

    Second, the alternatives provided by the error message don't work. It is impossible to import * as m from 'm', when that module has an export = function someFunction(){...}, resulting in an error:

    error TS2497: Module ''m'' resolves to a non-module entity and cannot be imported using this construct
    

    This makes it impossible to use many real-world CommonJs modules unless there's another way that I'm overlooking?

  3. mhegazy commented on Oct 26, 2017

    @mhegazy
    Contributor

    Not sure i understand your comment.. just write import * as m from "m" or use --module commonjs.

  4. janv commented on Oct 26, 2017

    @janv
    Author

    I am sorry, I tried to provide a minimal example, I might have omitted a relevant part.
    The declaration file for the module I'm importing in questions looks like this:

    declare module "m" {
      declare function m(s:string):void
      export = m
    }

    When I change the import statement as you describe (import * as m from "m"), typescript gives me the error message quoted in my last post (TS2497).

    I do not want to use commonjs as an output module format. I can understand that this might be an unsupported use case, my confusion just comes from the fact that according to the documentation, this should work. Search for "native ECMA" on https://www.typescriptlang.org/docs/handbook/modules.html

    I have my full test repo here: https://github.com/janv/import-assign-bug.
    In the index.ts you find both variants for imports, each with its respective error as a comment after the line. Run yarn start to build index.ts

    Sorry for this back and forth, thank you for looking into this. I have ways to work around my concrete problem, but I still think this is something worth looking into.

  5. aluanhaddad commented on Oct 27, 2017

    @aluanhaddad
    Contributor

    If "m" is a CommonJS or AMD module, the correct form of the import, and the one which currently typechecks (requires setting the --allowSyntheticDefaultImports compiler option) is

    import m from "m";

    Unfortunately, this will not work at runtime unless you are using SystemJS, a recent version of Webpack, or piping TypeScript's output through Babel.

    Resolving this is tracked by #16093

  6. mhegazy commented on Oct 27, 2017

    @mhegazy
    Contributor

    As Aluan Haddad (@aluanhaddad) mentioned, #16093 is the one you want to track for now.

  7. janv commented on Oct 30, 2017

    @janv
    Author

    Awesome to see you're already onto it :D

    Thanks a lot

  8. locked and limited conversation to collaborators on Jun 14, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions