angular: @Optional triggers warning "Can't resolve all parameters" with AOT-compilation (official documentation)

I’m submitting a…


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

With AOT-compilation enabled the example for @Optional at https://angular.io/api/core/Optional raises the following warning:

ng build --prod --aot=true
Warning: Can't resolve all parameters for Car in /private/tmp/foo/src/app/Car.ts: (?). This will become an error in Angular v6.x
...

With JIT-compilation there is not error.

Expected behavior

There should not be a warning.

Minimal reproduction of the problem with instructions

  1. Bootstrap project via ng new foo --version 1.7.4

  2. Add src/app/Car.ts with the following content

     import {Injectable, Optional} from '@angular/core';
    
     class Engine {
     }
    
     @Injectable()
     export class Car {
       constructor(@Optional() public engine: Engine) {
       }
     }
    

    NOTE: Class Car needs to be exported in order to trigger this error!

  3. Run ng build --prod --aot=true:

      10% building modules 4/4 modules 0 activeWarning: Can't resolve all parameters for Car in /private/tmp/foo/src/app/Car.ts: (?). This will become an error in Angular v6.x
     Warning: Can't resolve all parameters for Car in /private/tmp/foo/src/app/Car.ts: (?). This will become an error in Angular v6.x
     Date: 2018-06-15T06:54:12.105Z                                                          
     Hash: 500b30562c9f670e5970
     Time: 3837ms
     chunk {0} polyfills.515ed9df1f4876ab6cb6.bundle.js (polyfills) 59.8 kB [initial] [rendered]
     chunk {1} main.f46d9721702aed0cb018.bundle.js (main) 154 kB [initial] [rendered]
     chunk {2} styles.ac89bfdd6de82636b768.bundle.css (styles) 0 bytes [initial] [rendered]
     chunk {3} inline.318b50c57b4eba3d437b.bundle.js (inline) 796 bytes [entry] [rendered]
    

Environment

$ ng --version

    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/
    
Angular CLI: 1.7.4
Node: 8.9.4
OS: darwin x64
Angular: 5.2.11
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 1.7.4
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.3.2
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.2
@schematics/angular: 0.3.2
@schematics/package-update: 0.3.2
typescript: 2.5.3
webpack: 3.11.0

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 16
  • Comments: 21 (6 by maintainers)

Commits related to this issue

Most upvoted comments

There has not been a lot of activity or acknowledgement of this bug from the Angular contributors, Is this going to be fixed?

Tacking on here from another issue… as laid out by @csbenjamin here

This fails in both JIT and AOT.

export class MyService {
    constructor(@Optional() @Inject('MY_STRING_TOKEN') private myOptionalService) {}
}

and I don’t provide MY_STRING_TOKEN, the app works as expected and

this.myOptionalService === null

evaluates to true.

But if I do the following:

export const MY_NON_STRING_TOKEN = new InjectionToken<string>('MY_NON_STRING_TOKEN');
export class MyService {
    constructor(@Optional() @Inject(MY_NON_STRING_TOKEN) private myOptionalService) {}
}

even if I do provide something with this token, Angular throws an error:

Can’t resolve all parameters for MyService:

Can someone from the core team respond to whether or not this issue has been ever considered or has any plans on being addressed?

This bug fundamentally breaks hexagonal architectures where dependents may or may not exist.

A workaround that I’ve been using (accidentally until today) is to add the @Inject() decorator, as well.

constructor(
  @Optional() @Inject('TokenNoOneWillEverUse') private readonly myOptionalThing?: MyThing,
)

You need to add the class Engine to the module Also just add the demo repository right away

@NgModule({
  ...
  providers: [Engine]
})
export class AppModule {}