angular-cli: Suspect bug in current AOT implementation running ng serve vs. ng serve --prod

Bug Report or Feature Request (mark with an x)

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

Versions.

@angular/cli: 1.4.4
node: 8.5.0
os: darwin x64
@angular/animations: 4.4.4
@angular/common: 4.4.4
@angular/compiler: 4.4.4
@angular/core: 4.4.4
@angular/forms: 4.4.4
@angular/http: 4.4.4
@angular/platform-browser: 4.4.4
@angular/platform-browser-dynamic: 4.4.4
@angular/router: 4.4.4
@angular/upgrade: 4.4.4
@angular/cli: 1.4.4
@angular/compiler-cli: 4.4.4
typescript: 2.5.3

Repro steps.

I created the following service (which gets extended) which works fine in ng serve

import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";

// models
import {Question} from "../_models/question"

// environment
import {environment} from '../../environments/environment';

@Injectable()

abstract class ApiService {

  protected area;

  protected get URL() {
    return environment.apiURL + '/api/v2/' + this.area;
  }

  constructor(protected httpClient: HttpClient) {
  }

  public questions() {
    return this.httpClient.get(this.URL + '/questions');
  }

  public getQuestion(id: string) {
    return this.httpClient.get(this.URL + '/questions/' + id);
  }

  public tags(extended: boolean = false) {
    if (extended) {
      return this.httpClient.get(this.URL + '/tags/extended');
    } else {
      return this.httpClient.get(this.URL + '/tags');
    }
  }

  public updateQuestion(question: Question) {
    return this.httpClient.put(this.URL + '/questions/' + question._id, question);
  }

  public createQuestion(data: Question) {
    return this.httpClient.post(this.URL + '/questions/question', data);
  }

  public deleteQuestion(id: string) {
    return this.httpClient.delete(this.URL + '/questions/' + id);
  }

  public searchQuestions(terms) {
    return this.httpClient.post(this.URL + '/questions/search', terms);
  }

  public count() {
    return this.httpClient.get(this.URL + '/questions/count');
  }
}

export class ExamService extends ApiService {
  protected area = 'exam';
}

export class LessonService extends ApiService {
  protected area = 'lesson';
}

usage:

import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {ExamService} from '../_services/api.service';

@Component({
  templateUrl: 'dashboard.component.html'
})
export class DashboardComponent {
  public examStats: any = {};

  constructor(private examService: ExamService) {
  }

  ngOnInit() {

    this.examService.count()
      .subscribe((data: { total: number }) => {
        this.examStats.count = data.total;
      });

  }
}

When I run the same exact code via prod ng serve --prod I get the following error on the service:

vendor.9ead56f8ae9a0e9bc69c.bundle.js:1 ERROR TypeError: Cannot read property 'get' of undefined
    at e.t.tags (0.12dca0b4bedd46aac615.chunk.js:1)
    at l.UH1D.l.ngOnInit (6.d5388f69c020eaa085d0.chunk.js:1)
    at Mn (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at hr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at cr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at Hr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at Object.updateDirectives (6.d5388f69c020eaa085d0.chunk.js:1)
    at Object.updateDirectives (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at lr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at Mr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)

and when I go to the specific line of compiled code that triggers this is:

...?this.httpClient.get(this.URL+"/tags/extended"):this.httpClient.get(this.URL+"/tags")},t.prototype...

The log given by the failure.

vendor.9ead56f8ae9a0e9bc69c.bundle.js:1 ERROR TypeError: Cannot read property 'get' of undefined
    at e.t.tags (0.12dca0b4bedd46aac615.chunk.js:1)
    at l.UH1D.l.ngOnInit (6.d5388f69c020eaa085d0.chunk.js:1)
    at Mn (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at hr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at cr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at Hr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at Object.updateDirectives (6.d5388f69c020eaa085d0.chunk.js:1)
    at Object.updateDirectives (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at lr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)
    at Mr (vendor.9ead56f8ae9a0e9bc69c.bundle.js:1)

Desired functionality.

I suspect that this is bug in current AOT implementation. I’d expect them to behave the same way.

Mention any other details that might be useful.

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 15 (7 by maintainers)

Most upvoted comments

This seems like an issue related to the usage of extended classes for DI and not for the CLI, closing this issue.

That should work with AOT. I have services where the abstract base class and the derived class are both decorated @Injectable() and the constructor is only defined in the abstract base class. I don’t use ng serve, but it definitely works with the AOT compiler.