angular-cli: Running `ng test` fails with Uncaught ReferenceError: [TYPE_NAME] is not defined

Bug Report or Feature Request (mark with an x)

- [X] bug report -> please search issues before submitting
- [ ] feature request

Versions.

$ ng --version
    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/
@angular/cli: 1.0.0
node: 6.9.1
os: win32 x64
@angular/common: 4.0.0
@angular/compiler: 4.0.0
@angular/core: 4.0.0
@angular/forms: 4.0.0
@angular/http: 4.0.0
@angular/platform-browser: 4.0.0
@angular/platform-browser-dynamic: 4.0.0
@angular/router: 4.0.0
@angular/cli: 1.0.0
@angular/compiler-cli: 4.0.0

Windows 10

Repro steps.

Step 1 Run the following command

ng new myapp

Step 2 Add following file MyType.ts in the folder where the generate app.conponent.ts is located.

export class MyType {
    constructor(public id: string){}
}

Step 3 Modify app.conponent.ts so it looks like this:

import { Component, Input } from '@angular/core';
import { MyType } from "app/MyType";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';

  private selectedId: string;
  @Input() set setSelectedId(myType: MyType | undefined) {
    if (product !== undefined) {
      this.selectedId = myType.id;
    }
    else {
      this.selectedId = myType;
    }
  }
}

Step 4 Run the following command

ng test

The log given by the failure.

Result:

$ ng test
25 03 2017 07:37:40.092:WARN [karma]: No captured browser, open http://localhost:9876/
25 03 2017 07:37:40.107:INFO [karma]: Karma v1.4.1 server started at http://0.0.0.0:9876/
25 03 2017 07:37:40.108:INFO [launcher]: Launching browser Chrome with unlimited concurrency
25 03 2017 07:37:40.185:INFO [launcher]: Starting browser Chrome
25 03 2017 07:37:41.275:INFO [Chrome 57.0.2987 (Windows 10 0.0.0)]: Connected on socket 9t52BW0h_NVdN1zYAAAA with id 31811334
Chrome 57.0.2987 (Windows 10 0.0.0) ERROR
  Uncaught ReferenceError: MyType_1 is not defined
  at webpack:///src/app/app.component.ts:13:43 <- src/test.ts:52770

Chrome 57.0.2987 (Windows 10 0.0.0) ERROR
  Uncaught ReferenceError: MyType_1 is not defined
  at webpack:///src/app/app.component.ts:13:43 <- src/test.ts:52770

Desired functionality.

I would like to to have the test being run 😃

Mention any other details that might be useful.

App is working fine, so it seems to be only when running tests. I know that it worked in version 2.x of the cli and Im pretty sure it is related to the typescript version, where it worked with TS 2.0.x and not with TS 2.2.x.

Alto, it works if @Input is not used and app.component.ts looks this:

import { Component } from '@angular/core';
import { MyType } from "app/MyType";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';

  private selectedId: string;
  set setSelectedId(myType: MyType | undefined) {
    if (product !== undefined) {
      this.selectedId = myType.id;
    }
    else {
      this.selectedId = myType;
    }
  }
}

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 12
  • Comments: 26 (3 by maintainers)

Most upvoted comments

I had this problem not with the test but the main code itself when I upgraded from Angular 4.3.0 to 5.2.9 and Angular Material from 2.0.0-beta-2 to 5.2.4. The problem was an @Injected service inside a parent component.

export abstract class ParentComponent {
    constructor(@Inject(WhateverService) protected service: WhateverService,
            protected dialog: MatDialog, protected error: Error) { }
}

---

export class ChildComponent extends ParentComponent {
    constructor(service: WhateverService, dialog: MatDialog, error: Error) {
        super(service, dialog);
    }
}

That was giving the error:

ERROR Error: Uncaught (in promise): ReferenceError: material_1 is not defined
ReferenceError: material_1 is not defined

As wrong as it might look, it was working with the older versions.

Well, investigating the transpiled js, I saw that the material_1 was for the dialog and I spent hours in that parameter. Until I saw that if I put the MatDialog parameter first, the problem was transferred to the third parameter. That’s when I realized that the problem was with the service. So the solution for me was to put the @Inject annotation into the ChildCompoment (which makes more sense).

export abstract class ParentComponent {
    constructor(protected service: WhateverService,
            protected dialog: MatDialog, protected error: Error) { }
}

---

export class ChildComponent extends ParentComponent {
    constructor(@Inject(WhateverService) service: WhateverService,
            dialog: MatDialog, error: Error) {
        super(service, dialog);
    }
}

And now it’s working fine. Well, it might be a little unrelated to the issues you are reporting, but I hope it helps you to find the solution to your environment.

I’m sorry, but we can’t reproduce the problem following the instructions you provided. Remember that we have a large number of issues to resolve, and have only a limited amount of time to reproduce your issue. Short, explicit instructions make it much more likely we’ll be able to reproduce the problem so we can fix it.

If the problem persists, please open a new issue following our submission guidelines.

A good way to make a minimal repro is to create a new app via ng new repro-app and adding the minimum possible code to show the problem. Then you can push this repository to github and link it here.

I had the same issue initially with ng test as was provided in the description. It was fixed by changing module and target to es2015 and es6 appropriately . But after upgrading to ng 5.x even this fix stopped working + JIT compilation stopped working with the same error as well…

The another workaround for me was assigning the type which causes this error to any variable before class definition. With this fix everything started working even with initial module=commonjs ad target=es5. Here is an example:

import {MyIssueService} from 'path_to_service';
[other imports]

const hack = MyIssueService;
export class ConsumerClass {
   constructor(private service: MyIssueService) {
   }
   ...
}

@zakhenry @filipesilva I was just able to fix mine but doing something a bit crazy. I realized that components where I have an object (ex: MyObj) as an @Input parameter type but where I don’t use the type in the code in the module are the only modules giving me issues. So I added a usage of the type in the module and the issues goes away.

So if you have ‘MyObj’ as the type for the @Input with null, try adding a protected method to the component that simply returns a new instance of that type. Doesn’t have to be called, just has to use the type. Once I did that it worked again.

Example:

class MyComp {
   @Input() myObj: MyObj | null = null;

   protected _notCalled(): any {
      return new MyObj();
   }
}

Crazy hack I know, but it worked for me.

@zakhenry Oh yea, totally did not see that, sorry 😃

Another update. So I was able to find a temporary fix - in tsconfig.spec.json, change module to es2015 and target to es6. Mine looks like:

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/spec",
    "module": "es2015",
    "target": "es6",
    "baseUrl": "",
    "types": [
      "jasmine",
      "node",
      "faker"
    ]
  },
  "files": [
    "test.ts"
  ],
  "include": [
    "**/*.spec.ts",
    "**/*.d.ts"
  ]
}

This does not fix the issue however, as switching to targeting es6 is obviously risky when runtime uses es5, and it also breaks the coverage reporter completely.

Further investigation leads me to the direction of metadata reflection combined with interface unions, however I’m still stumped on a solution