webpack: Strange warning stating that export does not exist when it does

Bug report

What is the current behavior?

Not sure if this is a problem with a loader or webpack itself, but on a project that is using typescript, I’m getting a warning:

    WARNING in ./React/src/components/_shared/form/form-model.ts
    17:0-39 "export 'IValidation' was not found in '_types/IValidation'"
        at HarmonyExportImportedSpecifierDependency._getErrors (C:\project\node_modules\webpack\lib\dependencies\HarmonyExportImportedSpecifierDependency.js:352:11)
        at HarmonyExportImportedSpecifierDependency.getWarnings (C:\project\node_modules\webpack\lib\dependencies\HarmonyExportImportedSpecifierDependency.js:299:15)
        at Compilation.reportDependencyErrorsAndWarnings (C:\project\node_modules\webpack\lib\Compilation.js:985:24)
        at Compilation.finish (C:\project\node_modules\webpack\lib\Compilation.js:817:9)
        at hooks.make.callAsync.err (C:\project\node_modules\webpack\lib\Compiler.js:479:17)
        at _done (eval at create (C:\project\node_modules\tapable\lib\HookCodeFactory.js:24:12), <anonymous>:9:1)
        at _err0 (eval at create (C:\project\node_modules\tapable\lib\HookCodeFactory.js:24:12), <anonymous>:20:22)
        at _addModuleChain (C:\project\node_modules\webpack\lib\Compilation.js:758:12)
        at processModuleDependencies.err (C:\project\node_modules\webpack\lib\Compilation.js:697:9)
        at _combinedTickCallback (internal/process/next_tick.js:131:7)
        at process._tickCallback (internal/process/next_tick.js:180:9)

However, the file in question _types/IValidation, is imported in numerous other files without any warnings being emitted related to those other files that are also importing IValidation from _types/IValidation.

The contents of the file are simple, and there is an “export interface IValidation” in the file:

export enum ValidationType {
    Required,
    Min,
    Max,
    MinLength,
    MaxLength,
}

export interface IValidation {
    validationType: ValidationType;
    errorMessage?: string;
    minValue?: number;
    maxValue?: number;
    maxLength?: number;
    minLength?: number;
}

We do have our “src” directory set as a module resolution root in the resolve section of our webpack config, but I also tried importing the file with a relative path and still get the warning.

I am kind of wondering if this is related to typescript. We are using ts-loader, but we have it doing type checking only and are doing transpiling with babel.

If the current behavior is a bug, please provide the steps to reproduce. Not sure since I get the warning due to the import of the file in question in one file but not due to several other files that also import the same interface from the same file.

What is the expected behavior? It should not issue a warning about a missing export if the export clearly exists.

Other relevant information: webpack version: 4.8.3 Node.js version: 8.9.1 Operating System: Windows 10 Additional tools: webpack-cli 2.1.3

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 174
  • Comments: 74 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Maybe this is not a bug, its a feature! ™ 😃 See: https://github.com/Microsoft/TypeScript/issues/28481

When you export your TS interfaces/types in such a style so that it comply with TS’s isolatedModules=true, then you won’t get these webpack warnings.

import { State } from './interfaces';
export type State = State;

Hello. I create simple plugin for suppress this error. 👨‍💻

https://github.com/igorkamyshev/ignore-not-found-export-plugin

I think @MarekLacoAXA’s comment nails the issue for me. I had this error because I was exporting types the same way I was exporting constants. I then split them and used export type for the type alone and it worked. Here’s the code:

// ActionNames is a const and ActionTypes is a type

// Before
export { ActionNames, ActionTypes } from "./ActionTypes";

// Above line resulted in warning
// > "export 'ActionPayload' was not found in './ActionTypes'

// Changed the code to the following for the warning to disappear
export { ActionNames } from "./ActionTypes";
export type ActionPayload = ActionPayload;


We are facing the same issue using babel-loader with https://babeljs.io/docs/en/babel-plugin-transform-typescript

With TypeScript 3.8, you can now use import type { Blabla }, which fixes the issue (the import statement is removed after transpilation.

Just use import type {AnimType}... instead. Requires Typescript 3.8.

Just use import type {AnimType}... instead. Requires Typescript 3.8.

Actually, not for import but for export, this removes warning too:

export type { AnimType } from './anim'

This is still a workaround because this warning is caused by valid code, so there is some bug in webpack.

This workaround apparently no longer works as of TS 3.7; I’m getting this error:

error TS2440: Import declaration conflicts with local declaration of 'FormFieldProps'.

However, you can workaround this by renaming the import:

import { FormFieldProps as _FormFieldProps } from './form-field-props'
export type FormFieldProps = _FormFieldProps

For those interested, I’ve published a small article about this issue and how to fix it using TypeScript 3.8+: https://medium.com/@dSebastien/leveraging-type-only-imports-and-exports-with-typescript-3-8-5c1be8bd17fb

Interfaces no longer exist after transpiling. For webpack the export doesn’t exist.

The same problem here for TS types/interfaces after migrating from WP3 to WP4, multiple warnings:

VM606323 index.js:151 ./apps/client/state.ts 3:0-82
"export 'ChartElement' was not found in './cycles/ChartArea/chartElements'

I don’t use ts-loader or anything special just simple loader:

const ts = require('typescript')
const tsconfig = require('tsconfig')

const compilerOptions = tsconfig.loadSync(process.cwd()).config.compilerOptions

module.exports = function (source) {  
  const result = ts.transpile(source, { ...compilerOptions, ...this.query })
  return result
}

So it is not a problem of ts-loader

@anjunatl, yours seems to be a different issue. This one is about exporting interfaces in typescript and is well understood. There is a comment somewhere explaining it really well, but I currently can not find it. Basically the typescript compiler emits no code for interfaces, so webpack can not find them in the compiled module; except when a module consists of only interfaces. In that case the module will end up completely empty and then webpack will not investigate the exports.

You should probably create a new issue for your problem.

A Truely ridiculous workaround that somehow works is

// common/constants.ts
export const ACTIVE_FCIDS = ['Val1', 'Val2', 'Val3'] as const;
export type ACTIVE_FCID = 'Val1' |  'Val2' | 'Val3';

Issue:

import { ACTIVE_FCID } from 'common/constants';
....
@Input() fcId: ACTIVE_FCID

// Failed to compile.
// Attempted import error: 'ACTIVE_FCID' is not exported from 'common/constants'

Work around:

import { ACTIVE_FCID } from 'common/constants';
....
@Input() fcId: ACTIVE_FCID | ACTIVE_FCID // Seriously!

// Compiled successfully!

@garyo solution also works if we seperate the ACTIVE_FCIDS and the type ACTIVE_FCID into separate files.

The workaround forces the user to make a distinction between the types of the symbols being exported, which is not always possible nor necessary. Whether something is a class type, or an interface, enum, or type, shouldn’t change how it is imported into the code.

Therefore I’d say the workaround is not a valid workaround. It requires making a change to valid code to satisfy an incorrect warning.

This will be fixed in typescript 3.8 by this PR: https://github.com/microsoft/TypeScript/pull/35200 Then you will be able to explicitely mark type imports like this (from the PR):

import type T from './mod';
import type { A, B } from './mod';
import type * as Types from './mod';

export type { T };
export type { T } from './mod';

Also compare the announcement for typescript 3.8 beta.

I just stumbled upon this issue and I’m wondering about a specific case where webpack/HarmonyImportSpecifierDependency seems to be unable to resolve a decorated + typed class member type, even though it works for another one that gets imported from the same file.

// types.ts
export type ComponentId = string;

export type ItemId = string;
// MyComponent.vue
import { Prop } from './decorators';
import { ComponentId, ItemId } from './types';

export default class MyComponent extends Vue {
  @Prop() readonly id!: ComponentId;

  generateItemId(): ItemId {
    return '123';
  } 
}

In this case, the ComponentId type “cannot be found”, whereas the ItemId can. I’m really not sure what’s going on here and why it works for one but not for the other - it doesn’t look to me as if this would have something to do with how the import file is resolved.

"export 'ComponentId' was not found in './types'

Declaring another function with the ComponentId as return type doesn’t change this behavior, only when the decorator itself is gone makes it properly work again.

Have you tried the following?

// MyComponent.vue
import { Prop } from './decorators';
import type { ComponentId, ItemId } from './types'; // <---- adding type here

@igorkamyshev somehow, no matter using stats or your plugin, I’m still getting errors 😕

Sorry, it was deprecated. =(

Update: Some of the files the warnings fired for had both export function X and export default function X snippets in them, some just had one export default function X snippet. All of the warnings went away when I removed all of the default keywords. Hope this helps.

From https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/:

As a solution in TypeScript 3.8, we’ve added a new syntax for type-only imports and exports.

import type { SomeThing } from "./some-module.js";

export type { SomeThing };

The solution proposed by @MarekLacoAXA doesn’t work if the exported type requires generics

I guess, it’s related to ts-loader then …

Perhaps it would be awesome if you could create a simple project that would reproduce your bug and upload on github.

@elado You can set "importsNotUsedAsValues": "error" in tsconfig: https://www.typescriptlang.org/tsconfig#importsNotUsedAsValues

That still allows mixed imports, consisting of both types & values. If you want to ensure types are only imported via import type, you can use the @typescript-eslint/consistent-type-imports ESLint rule.

The following works for me:

parser: {
  javascript: {
    importExportsPresence: false
  }
}

importExportsPresence

I was getting this warning on all imports on types in my project after upgrading WebPack 4.41.6 to 5.74.0. It’s a large project, so it would not be possible to refactor to type imports everywhere.

Adding the following will silence the warnings from webpack:

module.exports = {
  ...
  module: {
    parser: {
      javascript: {
        reexportExportsPresence: 'false',
      },
    },
  },
 ...
};

Typescript introduced type-only exports/import which allows to generate valid JS code when compiling each file on it’s own. Without type-only exports/import the TS to JS transformation can’t be done when compiling each file on it’s own. It’s only possible with a full/partial graph of the modules. This is how typescript is designed. There is nothing to do on webpack-side here.

Yeah having the same issue, but weird part is that it’s only affecting single interface import in one specific file and I simply can’t come up with any ideas why.

any concrete solution for this yet?

Can confirm: moving types/interfaces away from any concrete stuff (into a separated file), is an ugly, but working workaround.

The only workaround I have found for this is to move all exported types and interfaces into a separate types.ts file and update all the imports everywhere to use that. It seems a pretty bad footgun that adding one class to a ts file that formerly happened to be all types and interfaces suddenly causes these warnings. I’m not clear if the issue is with typescript (emitting only half of what webpack needs?) or with webpack being unable to tell that things are OK.

FWIW I only just started seeing this issue today in one of my react/redux/saga projects after refactoring my code layout from:

PageSagas.js
PageActions.js
PageReducers.js

to

feature-A/sagas.js
feature-A/actions.js
feature-A/reducers.js
feature-B/sagas.js
feature-B/actions.js
feature-B/reducers.js
PageSagas.js
PageActions.js
PageReducers.js

to try to organize the growing project a bit more.

Not sure if the duplicate filenames across feature folders could have anything to do with this weird warning display issue.

And because more detail doesn’t hurt with debugging, in my particular case the exported function names don’t match the filenames right now. They currently look like:

// feature-A/reducers.js :
export default function featureAReducer(...) {}

instead of

// feature-A/reducers.js :
export default function reducers(...) {}

Hope this helps with the debugging. In the meantime, @igorkamyshev 's plugin looks good.

Webpack version info:

@andresesfm import type did it! Thank you!

I just stumbled upon this issue and I’m wondering about a specific case where webpack/HarmonyImportSpecifierDependency seems to be unable to resolve a decorated + typed class member type, even though it works for another one that gets imported from the same file.

// types.ts
export type ComponentId = string;

export type ItemId = string;
// MyComponent.vue
import { Prop } from './decorators';
import { ComponentId, ItemId } from './types';

export default class MyComponent extends Vue {
  @Prop() readonly id!: ComponentId;

  generateItemId(): ItemId {
    return '123';
  } 
}

In this case, the ComponentId type “cannot be found”, whereas the ItemId can. I’m really not sure what’s going on here and why it works for one but not for the other - it doesn’t look to me as if this would have something to do with how the import file is resolved.

"export 'ComponentId' was not found in './types'

Declaring another function with the ComponentId as return type doesn’t change this behavior, only when the decorator itself is gone makes it properly work again.

It has something to do with the decorator see if this works for you: https://github.com/webpack/webpack/issues/7378#issuecomment-617880809

In my project only the @input() variables showed this behavior this is definiltly a webpack issue and it’s disappointing that it has been closed.

Not sure if it happened to me for the same reason as to everyone else here, but in my case it happened because I used enum values as keys in my interface - like this:

export interface IDummyInterface {
    [eDummyEnum.A]: string;
}

Maybe it’ll help someone

@pcx can you please clarify your example? What is AcitonPayload and where it ist defined? Maybe you can edit the answer and show the relevant code in ActionTypes

For me this with TS using export {} from construct causes the issues.

import { AnimType } from './anim' // because need to use in this module
export { AnimType } from './anim' // because want it be avaialbled to import from this module 

This causes warning: "export 'AnimType' was not found in './anim'

To workaround:

import { AnimType as _AnimType } from './anim'
export type AnimType = _AnimType

Is there any way to treat these warnings as errors? I want my build to fail if it shows up. Currently both build and type check (tsc --noEmit) succeed so there’s no way to catch this early.

@andresesfm I have an index.ts file which reexports the types. Using export type { MyTypeOrInterface } from './MyTypeOrInterface' did the trick. Thanks!

I just stumbled upon this issue and I’m wondering about a specific case where webpack/HarmonyImportSpecifierDependency seems to be unable to resolve a decorated + typed class member type, even though it works for another one that gets imported from the same file.

// types.ts
export type ComponentId = string;

export type ItemId = string;
// MyComponent.vue
import { Prop } from './decorators';
import { ComponentId, ItemId } from './types';

export default class MyComponent extends Vue {
  @Prop() readonly id!: ComponentId;

  generateItemId(): ItemId {
    return '123';
  } 
}

In this case, the ComponentId type “cannot be found”, whereas the ItemId can. I’m really not sure what’s going on here and why it works for one but not for the other - it doesn’t look to me as if this would have something to do with how the import file is resolved.

"export 'ComponentId' was not found in './types'

Declaring another function with the ComponentId as return type doesn’t change this behavior, only when the decorator itself is gone makes it properly work again.

Hi,

I have a simliar problem in vue.

userDetails.ts

class UserDetails implements IUserDetails {
  accountDisabled?: boolean
  accountExpiry?: Date
  username: string
  ...
}
export { UserDetails }

userDetails.vue

<script lang="ts">
import Vue from 'vue'

import { UserDetails } from './userDetails'
...
</script>

Error message:

"export ‘UserDetails’ was not found in ‘./userDetails’

@lonewarrior556 , thought I would share a better way to code your example (in case you were unaware).

export const ACTIVE_FCIDS = <const> ['Val1', 'Val2', 'Val3'] ;
export type ACTIVE_FCID = typeof ACTIVE_FCIDS[number]

…now your code is dry.

https://github.com/tommyc38/nest-pipe-repro

Above is repro…This issue is actually more than a warning and blows up when using class-validator in a mono repo. Instructions are in the README, should be easy to reproduce but let me know if there are any issues. You can see Storybook blowup while Angular actually doesn’t have any issues. Angular should run fine in Storybook.

@dsebastien thank you for your article! Hopefully this helps solve the issue.

@igorkamyshev somehow, no matter using stats or your plugin, I’m still getting errors 😕

On the linked thread I’ve put details, a suggestion for implementation and an offer of help if someone wants to submit a PR. Let’s see what happens! ❤️ 🌻

@johnnyreilly Can you help us on this?

True, typescript would remove the interfaces but should also remove the imports.

I’m not sure where the warning is coming from (maybe not from webpack itself).

I’ll do some testing and see if I can figure it out.

We never had this happen on webpack 3.10 (were trying to upgrade to 4.8.3).