angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.73k stars 11.98k forks source link

Warnings when using an exported interface in a class #2034

Closed Maistho closed 7 years ago

Maistho commented 8 years ago

1. OS

Arch Linux

Linux maistho-laptop 4.7.2-1-ARCH #1 SMP PREEMPT Sat Aug 20 23:02:56 CEST 2016 x86_64 GNU/Linux

2. Versions

angular-cli: 1.0.0-beta.11-webpack.8
node: 6.5.0
os: linux x64

3. Repro steps

I started a new repository, and added a new empty service, with an exported interface.

Complete changes, and a repo to pull and see the issue, can be found here:

https://github.com/Maistho/angular-cli-input-issue/commit/e5c483081bfd7af3dafd0db074179b3090668e27

After running ng build, I get two warnings in the Terminal

4. The log given by the failure

Hash: 354e709ba2cf588db59a                                                                                                                                                                                          
Version: webpack 2.1.0-beta.21
Time: 11161ms
            Asset       Size  Chunks             Chunk Names
   main.bundle.js    2.51 MB    0, 2  [emitted]  main
 styles.bundle.js    10.2 kB    1, 2  [emitted]  styles
        inline.js    5.53 kB       2  [emitted]  inline
         main.map     3.1 MB    0, 2  [emitted]  main
       styles.map    14.1 kB    1, 2  [emitted]  styles
       inline.map    5.59 kB       2  [emitted]  inline
       index.html  489 bytes          [emitted]  
assets/.npmignore    0 bytes          [emitted]  
chunk    {0} main.bundle.js, main.map (main) 2.46 MB {1} [initial] [rendered]
chunk    {1} styles.bundle.js, styles.map (styles) 9.96 kB {2} [initial] [rendered]
chunk    {2} inline.js, inline.map (inline) 0 bytes [entry] [rendered]

WARNING in ./src/app/app.component.ts
18:55 export 'TestInterface' was not found in './test.service'

WARNING in ./src/app/app.component.ts
18:88 export 'TestInterface' was not found in './test.service'
Child html-webpack-plugin for "index.html":
         Asset     Size  Chunks       Chunk Names
    index.html  2.82 kB       0       
    chunk    {0} index.html 357 bytes [entry] [rendered]

5. Mention any other details that might be useful.

I could not reproduce the issue without adding the @Input() to the class member.

Compiling with tsc does not produce any warnings.

slubowsky commented 8 years ago

I get same issue when following the the dependency injection token example given in the angular docs - https://angular.io/docs/ts/latest/guide/dependency-injection.html#dependency-injection-tokens

Haven't checked if perhaps the docs have been updated but implemented in my app based on documentation as of maybe 2 months ago I get the following warning: export 'AppConfig' was not found in '../app.config' Whenever I import the interface.

Works fine despite warning so I've just been waiting for it to go away eventually as things mature

filipesilva commented 8 years ago

@TheLarkInn can you weight in?

xwb1989 commented 8 years ago

Seeing the very same error as well.

TheLarkInn commented 8 years ago

This is a bug we identified but I need to find it in our webpack repo to link to this one.

talsi commented 7 years ago

having the same issue. (Works fine despite warning) are you exporting more than one interface/class/const from the file? issue stopped for me after i exported each interface from its own dedicated file.

meaning if i had one file with multiple exports - i got warnings in build (export 'MyInterface1' was not found in '../file')

file.ts

export interface MyInterface1 {}
export interface MyInterface2 {}

after refactor - no warning

file1.ts

export interface MyInterface1 {}

file2.ts

export interface MyInterface2 {}
wulfsberg commented 7 years ago

Usually (and coming from the Java world), I'd consider it good style to split such multiple definitions into separate files anyway. But given how Angular recommends injecting interfaces (with an OpaqueToken), it seems obvious to define the interface and its related token in the same file, triggering this error.

teledemic commented 7 years ago

This issue is fixed for me after upgrading to angular-cli 1.0.0-beta.17 and angular 2.1.0

Maistho commented 7 years ago

@teledemic interesting, I still have the same problem on those versions.

teledemic commented 7 years ago

Huh! I recently upgraded all my packages. Not sure what it could have been other than those two. FWIW:

  "dependencies": {
    "@angular/common": "2.1.0",
    "@angular/compiler": "2.1.0",
    "@angular/core": "2.1.0",
    "@angular/forms": "2.1.0",
    "@angular/http": "2.1.0",
    "@angular/platform-browser": "2.1.0",
    "@angular/platform-browser-dynamic": "2.1.0",
    "@angular/router": "3.1.0",
    "angular2-highcharts": "^0.3.4",
    "bootstrap": "4.0.0-alpha.4",
    "core-js": "^2.4.1",
    "jwt-decode": "2.1.0",
    "ng2-bootstrap": "^1.1.14",
    "rxjs": "5.0.0-rc.1",
    "ts-helpers": "^1.1.1",
    "zone.js": "^0.6.25"
  },
  "devDependencies": {
    "@types/jasmine": "^2.5.35",
    "@types/jwt-decode": "1.4.28",
    "angular-cli": "^1.0.0-beta.17",
    "codelyzer": "~1.0.0-beta.1",
    "jasmine-core": "2.5.2",
    "jasmine-spec-reporter": "2.7.0",
    "karma": "1.3.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-cli": "^1.0.1",
    "karma-jasmine": "^1.0.2",
    "karma-remap-istanbul": "^0.2.1",
    "protractor": "4.0.9",
    "ts-node": "1.4.3",
    "tslint": "3.15.1",
    "typescript": "^2.0.3"
  }
wulfsberg commented 7 years ago

I'm on Angular 2.1.0 and CLI beta 17. I have a structure looking like this:

import { OpaqueToken } from '@angular/core';

export const APP_CONFIG = new OpaqueToken('app.config');

export interface AppConfig {
  geoserverUrl: string;
  ...
}

which triggers a Warning: export 'AppConfig' was not found in '../../app.config' whenever I try to inject the named token, e.g.

constructor(private http: Http, @Inject(APP_CONFIG) private appConfig: AppConfig) {
  ...
}

If I make the AppConfig a class, it works without warnings. (Though of course it then has to be instantiated differently). I makes me wonder if something in the build sequence just throws away the interfaces (too early), since they don't actually exist in the final JavaScript.

Iverson commented 7 years ago

Same issue with @Input property decorator. Found workaround:

@Input() myProp = <MyInterface1>null

instead of

@Input() myProp: MyInterface1

now no warnings

jmsegrev commented 7 years ago

Can anybody update on the status of this?. I'm at v1.0.0-beta.21, and still getting the warnings.

elmartino commented 7 years ago

I get an error in CLI: Cannot find name 'HERO_DI_CONFIG'. (followed complete example on angular documentation). Despite the error, all is working fine an chrome console doesn't log any errors.

tcoz commented 7 years ago

Just to add what knowledge I can, if you are using the APP_CONFIG example and getting the harmony warning, I moved the interface declaration (and just the interface declartion) into another file (iapp.config.ts),

export interface IAppConfig {
  API_URL: string;
}

imported IAppConfig into app.config.ts (since it is now in another file), and did the imports in the components separately, e.g:

import { APP_CONFIG } from '../app.config';
import { IAppConfig } from '../iapp-config';

Everything else remained the same (didn't have to convert it to a class etc). The extra file/imports are bulky, but no warnings and works as expected.

itsnotvalid commented 7 years ago

Recently trying to create a service provider (yup, also following the DI guide at https://angular.io/docs/ts/latest/guide/dependency-injection.html#!#injector-providers) and I copied the code into the hero.service.provider.ts file. It seems that it demands the file to export CamelCase instead of camelCase.

catull commented 7 years ago

Took @Maistho repo for a spin.

After ng init, overwriting most files except for app.component.*.ts. ng build still gives the warning:

Hash: cad6eef25bd1670f6646
Time: 10163ms
chunk    {0} main.bundle.js, main.bundle.map (main) 5.23 kB {2} [initial] [rendered]
chunk    {1} styles.bundle.css, styles.bundle.map, styles.bundle.map (styles) 1.77 kB {3} [initial] [rendered]
chunk    {2} vendor.bundle.js, vendor.bundle.map (vendor) 2.61 MB [initial] [rendered]
chunk    {3} inline.bundle.js, inline.bundle.map (inline) 0 bytes [entry] [rendered]

WARNING in ./src/app/app.component.ts
18:55-68 "export 'TestInterface' was not found in './test.service'

WARNING in ./src/app/app.component.ts
18:88-101 "export 'TestInterface' was not found in './test.service'

ng version is

                         _                           _  _

_ | | _ | |() / || '_ \ / _ || | | || | / _` || '| / || || | | (| || | | || (| || || || || (| || | ||| ( | || | _,||| || _, | _,||| _,||| \||||| |___/ angular-cli: 1.0.0-beta.26 node: 7.4.0 os: darwin x64 @angular/common: 2.4.4 @angular/compiler: 2.4.4 @angular/core: 2.4.4 @angular/forms: 2.4.4 @angular/http: 2.4.4 @angular/platform-browser: 2.4.4 @angular/platform-browser-dynamic: 2.4.4 @angular/router: 3.4.4 @angular/compiler-cli: 2.4.4

colthreepv commented 7 years ago

I still have this warning, as @catull reported.

The current workaround that @Iverson suggested works for me. But I didn't understand what it meant at first. It's a typescript type cast, it says "in myProp there is a null value (initially), but it WILL be of type MyInterface1

It can also be written as: @Input() myProp = null as MyInterface1;

CalebMacdonaldBlack commented 7 years ago

I'd really like to see this resolved

adamrkerr commented 7 years ago

I am still experiencing exactly the issue described by @wulfsberg.

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'

As this seems to be legal (and recommended) code, it would be better if it did not throw a warning.

anodynos commented 7 years ago

There is simpler & better solution: move all interfaces in a relevant `myfunctionality.interfaces.ts' with a normal exports

export interface MyFunctionality {
   foo: string;
}

and it works like a charm, with no warnings. And it separates your interfaces into their own files, which is nice.

scheysni commented 7 years ago

This issue is very annoying. Could you please fix it?

broij commented 7 years ago

Also waiting this issue to be fixed since a long time..

stefanaerts commented 7 years ago

If you extend an interface the warning remains when you split the interfaces in files image

ShadowManu commented 7 years ago

This is getting more attention from users than it should, and less attention from maintainers as I see the dates. Anyway, I come here not to complain (since I know the problem is hard), but to provide a valid workaround.

Our team uses a lot of interfaces. But also a lot of barrels (those index files where you simply re-export public stuff). A workaround that is working perfectly for us is using explicit re-exports, i.e:

Instead of using `export from './file-with-interfaces';in thatindex.ts, we doexport { SomeClass, SomeType, AnInterface1, AnInterface2 } from './file-with-interfaces';`*

Later using import { SomeClass, AnInterface1, OtherClass } from './the-folder-with-barrel'; works in the app and shows no warnings. I expect this may help some sorrowful souls ;).

PS: we have 62 interfaces and 0 warnings with this method ;)

anodynos commented 7 years ago

I made the same suggestion as @ShadowManu just above and got 3 negative votes - it 'd be nice if you explained your reasons :+1:

wulfsberg commented 7 years ago

@anodynos Fragmenting your code into double the number of files to use an Angular-ideomatic OpaqueToken is sub-optimal. As I mentioned, I come from the Java world and am fairly used to the "one file, one interface" style, but in this case it really feels like the wrong thing to do. (And from a language perspective, it should just work).

tcoz commented 7 years ago

Vanilla ES6/ES7 rules!!!

ducks

ShadowManu commented 7 years ago

@anodynos there's a couple of differences though. 1) you're not forced to put interfaces aside. Just put them where you deem necessary. 2) The barrel with explicit re-exports is somehow (yeah, I don't get the particular reason) the one making the warnings go away.

broij commented 7 years ago

@anodynos @ShadowManu The solutions you suggest don't solve the problem, they are just workarounds:

anodynos commented 7 years ago

Thanks @JulienBroi - some some comments:

wulfsberg commented 7 years ago

I don't need it, but I want it, the language allows it, and Angular recommends it. Insisting that I have to do it in another way because of a bug is not a good solution.

ShadowManu commented 7 years ago

It is a workaround and shouldn't be needed. But for those desperate, there's something that can be done in the meantime. Reverting is later as simple as deleting the files and following the broken imports.

MazeChaZer commented 7 years ago

Could a maintainer lock this issue? I'm getting my inbox spammed and none of these comments are helpful.

catull commented 7 years ago

@MazeChaZer All you need to do is to click on the "Unsubscribe" button above on the side.

MazeChaZer commented 7 years ago

@catull I would like to get notified when this issue is resolved

victornoel commented 7 years ago

For the record, the corresponding issue in webpack is webpack/webpack#2977.

As @hccampos explains there, it touches classes with decorators (annotations):

classes that contain decorators and are using an interface imported from another file trigger the warning. While everything works normally, it would be nice to get rid of the warnings.

Personally I can say it is actually only for the class of a class member annotated with @Input that I see the problem, it is not because of the class itself:

@Input() component: IComponentRow;

will trigger:

WARNING in ./src/app/features/cockpit/workspaces/petals-content/petals-component-view/petals-component-overview/petals-component-overview.component.ts
46:50-63 "export 'IComponentRow' was not found in '../../../state/components/component.interface'

The problem is not because of webpack but most certainly because of something typescript/decorators related (as explained by @sokra: https://github.com/webpack/webpack/issues/2977#issuecomment-245887841). The interface is referenced in the javascript code generated by typescript and thus webpack can't find it (since they have no real existence in the javascript realm).

@filipesilva so I think the problem is coming from typescript itself.

johnpapa commented 7 years ago

I have a similar situation. I have multiple interfaces in the same file, all exported. From other files I import those and get a warning that it cannot find them. If I split each interface to its own file, the warning goes away.

Sometimes I have interfaces and classes in the same file, same result when importing the interfaces.

368:57-64 "export 'IConfig' was not found in '../models/app-insights'
export interface IAppInsights {
  // ...
}
import { IConfig } from '../models/app-insights';
// ...

Things that worked:

  1. split each interface to its own file
  2. make them abstract classes

VS Code is happy with this. VS Code can find the import, can navigate to the definition. So it seems to be OK using TypeScript ... but the compiler is not.

cc @alexeagle as an FYI

Ths appears to be a TypeScript thing. ?

pajics commented 7 years ago

we changed our tsconfig.js module from es6 to commonjs and warnings were gone, based on generated code I'm not sure whats different.

Input decorator code with es6: decorate([ webpack_require.i(WEBPACK_IMPORTED_MODULE_0angular_core["Input"])(), metadata('design:type', (typeof (_a = typeof WEBPACK_IMPORTED_MODULE_1models_user_info["UserInfo"] !== 'undefined' && __WEBPACK_IMPORTED_MODULE_1models_user_info["UserInfo"]) === 'function' && _a) || Object) ], HeaderComponent.prototype, "user", void 0);

Input decorator code with commonjs: __decorate([ core_1.Input(), __metadata('design:type', (typeof (_a = typeof user_info_1.UserInfo !== 'undefined' && user_info_1.UserInfo) === 'function' && _a) || Object) ], HeaderComponent.prototype, "user", void 0);

alexeagle commented 7 years ago

We need a better way to isolate which layer is causing the problem - it seems like angular CLI magic is making this difficult. Perhaps a minimal repro without the CLI would help?

johnpapa commented 7 years ago

@alexeagle I dont have a minimal repro, though I will try to find a better one.

In the meantime, if you clone this repo and branch, run npm i, then run ng b you will see the issues I mentioned.

https://github.com/projectkudu/AzureFunctionsPortal/tree/upgrade-angular-v4

alexeagle commented 7 years ago

Sorry, I won't have time to dig in today. The warning does come from webpack, right? Could it be that TypeScript has erased the interface from the output .js file, but some other code still references it? (try pasting the .ts content in the TypeScript playground to see what it emits)

johnpapa commented 7 years ago

No worries, no rush. It's a warning, not an error.

The typescript compiler outputs an empty file. But there are other interfaces in that file which are fine.

Another interesting observation is that if I move each interface to its own file, the warning goes away

rolandjitsu commented 7 years ago

I am also experiencing the same thing, but it happens with type aliases export type MyTypeAlias = .... as well, not just interfaces.

jasonburrows commented 7 years ago

I used to just be able to ignore this warning, but now after upgrading to @angular/cli 1.0.1 it will give an error in the browser saying "Failed to compile" along with the error about my interface not being found in the source file. Why is a warning stopping it from running?

manofearth commented 7 years ago

In @angular/cli: 1.0.1 I have not warning, but error:

2017-04-26

Should I put every single interface or type in a separate file? Even very small? For example:

export type SelectorDataMapperFn<T> = (term?: string) => Observable<T[]>;
export type SelectorListItemMapperFn<T> = (value: T) => SelectorSelectItem<T>;
export type SelectorCompareWithFn<T> = (value1: T, value2: T) => boolean;
export type SelectorCreateNewItemFn<T> = (value: string) => void;

In separate file each? Is it all right?

CSchulz commented 7 years ago

@manofearth At the moment it is the only possibility to get around the error.

MattMorrisDev commented 7 years ago

Yeah, updating from 1.0.0 to 1.0.1 prevents the UI from loading at all now. The errors displayed (like in @manofearth 's picture) are still displayed in the console logs as "WARNING"s though - not errors. 1.0.0 doesn't block the UI though.

manofearth commented 7 years ago

I found that error disappears if I switch imports from import { X } from './x' to import * as ModuleX from './x'. But it's not very convinient to prepend all X usages in code with module alias: ModuleX.X.

johnjerrico commented 7 years ago

Hi, ` // test.ts export interface test {}

// app.ts import { test } from './test' ` I don't get any warning but the import resulting undefined

elvisbegovic commented 7 years ago

same issue