2.1.0-beta.22 shows an export-not-found warning for an existing, exported class

I’m submitting a bug report

Webpack version:
2.1.0-beta.22

Please tell us about your environment:
Windows 10

Current behavior:
https://github.com/Tragetaschen/webpack-interface-import-warning
When running webpack beta.22, two warnings appear:

WARNING in ./main.ts
16:51 export 'Bar' was not found in './src'

WARNING in ./main.ts
16:74 export 'Bar' was not found in './src'

Expected/desired behavior:
beta.21 doesn’t show these.

There are some ways to make the warning go away:

  • In src/index.ts, replace export * from './bar' with export {Bar} from './bar'
  • In src/index.ts, comment out export * from './foo' (sic!)

I can see that the awesome-typescript-loader introduces code that references the interface name (although running bare TypeScript erases it successfully), but those two workarounds above make me think something is odd with webpack.

Author: Fantashit

11 thoughts on “2.1.0-beta.22 shows an export-not-found warning for an existing, exported class

  1. typescript transpiles export interface Bar {} to nothing. This means there is nothing exported from bar. webpack correctly shows a warning that the export was not found.

    The problem is that the exported interface is really used in the generated type:

    __decorate([
        metadata(), 
        __metadata('design:type', (typeof (_a = typeof Bar !== 'undefined' && Bar) === 'function' && _a) || Object)
    ], Main.prototype, "prop", void 0);

    Note that the code still works, because typescript checks for undefined here, but a ES6 Modules implementation may throw here (webpack displays a warning).

    Please report this issue to typescript itself.

    It should either generate an export from interface.
    Or it should not use the imported variable if it’s an interface (which is not generated).

  2. I experience this same issue using awesome-typescript-loader. ts-loader doesn’t seem to have this issue.

  3. Same issue with string literal types.

    Consider moduleA.ts:

    export type AvatarType = 'avatar' | 'storecover';

    Then import it in moduleB.ts:

    import { AvatarType } from './moduleA';
    
    let avatar: AvatarType = 'avatar'; // <-- This line gives warning

    WARNING: export ‘AvatarType’ was not found in ‘./moduleA’

  4. We also get similar warnings here, in one case a string enum type id not found eg.
    export type Provider = 'asdf' | 'bsdf' | ...;

    In the other an interface definition is not found.

    export interface IMessageComponent {
        type: string; // tslint:disable-line
        text: string;
    }
    
    export interface IMessageEmoticonComponent extends IMessageComponent {
        type: 'emoticon'; // tslint:disable-line
        pack: string;
        source: string;
        coords: {
            x: number,
            y: number,
            width: number,
            height: number,
        };
    }
    
  5. TypeScript should be eliding any imports that aren’t used as values. I’m not sure what could be going on here.

  6. Just ran into this on an angular-cli project which is using Webpack 2.1.0-beta.24 and awesome-typescript-loader 2.2.4. Warning occurs when I export a string literal type from one file and import it in another.

  7. I am still experiencing this issue while following the config example.

    import { OpaqueToken } from '@angular/core';
    
    export let SKYPE_CONFIG_TOKEN = new OpaqueToken('skype.config');
    
    export interface SkypeConfig {
        ...
    }
    

    Everything works, but I get this warning:

    105:93-104 "export 'SkypeConfig' was not found in './skype.config'

  8. I noticed this warning occurs when there is more than one export in the file where the interface is declared… so isolating the interface in one file and moving everything else to it’s own file fixes the issue.

    Not sure why this is happening, but thankfully, no more warnings.

  9. Sorry @Markus-ipse. Will have to call BS on that. What you’re saying here makes no sense. Destructuring or not, import { f1 } from ‘./moduleA’ is the correct syntax.

    @mrchief Well yes, it’s correct syntax, but what I was saying is that you cannot use that syntax for destructuring out a value from an exported object.

    From the example you linked to:

    // module "my-module.js"
    function cube(x) {
      return x * x * x;
    }
    const foo = Math.PI + Math.SQRT2;
    export { cube, foo };
    

    Even though the above export statement looks like an object, it is not, it’s two named exports. It’s equivalent to writing:

    // module "my-module.js"
    export function cube(x) {
      return x * x * x;
    }
    export const foo = Math.PI + Math.SQRT2;
    

    As you can have multiple named exports in a file, we have the following syntax which allow us to pick which exports that we want to import:

    import { cube, foo } from 'my-module';
    

    If you are using a default export to export an object, as in Pavel’s example:

    const f1 = () => {};
    export default {
        f1,
    };
    
    

    Then you must use the default import statement:

    import whatEverNameIWant from './moduleA';
    

    This will give you the exported object on which you can call the f1 function:

    whatEverNameIWant.f1();
    

    So even though the named import statement looks like object destructuring, it is in fact not, and that is what is causing the confusion.

    So for Pavel’s example to work without warning, both the import and exports must be either named or default, e.g.

    //moduleA.js
    
    const f1 = () => {};
    export { 
        f1,
    };
    
    // or export const f1 = () => {};
    
    
    //moduleB.js
    import { f1 } from './moduleA';
    f1();
    
    

    or

    //moduleA.js
    
    const f1 = () => {};
    export default {
        f1,
    };
    
    //moduleB.js
    
    import myModule from './moduleA':
    const { f1 } = myModule;
    f1();
    
    // or myModule.f1();
    
    

    Hope that make it clearer 🙂

  10. Now its my turn to apologize @Markus-ipse ! I missed one significant detail earlier – export default vs export {. Yes I see the confusion now.

    Thanks for the detailed response. Would have not wasted your time if my eyes could read better. 👁️

Comments are closed.