question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IVY: Cannot use @Optional in abstract base class

See original GitHub issue

🐞 bug report

Affected Package

@angular/core

Is this a regression?

Yes, compiling without IVY works as expected

Description

When you create an abstract base class with a constructor parameter marked with the @Optional decorator, Ivy will not compile because it cannot find a suitable injection token

🔬 Minimal Reproduction

https://github.com/a88zach/ivy-bug/tree/bug/optional

🔥 Exception or Error


ERROR in src/app/app.component.ts:9:27 - error TS-992003: No suitable injection token for parameter 'optionalVar' of class 'AppBaseComponent'.
Found string

9   constructor(@Optional() optionalVar?: string) {

🌍 Your Environment

Angular Version:


Angular CLI: 9.0.0-rc.4
Node: 10.15.3
OS: darwin x64

Angular: 9.0.0-rc.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.0-rc.4
@angular-devkit/build-angular     0.900.0-rc.4
@angular-devkit/build-optimizer   0.900.0-rc.4
@angular-devkit/build-webpack     0.900.0-rc.4
@angular-devkit/core              9.0.0-rc.4
@angular-devkit/schematics        9.0.0-rc.4
@angular/localize                 9.0.0-rc.0
@ngtools/webpack                  9.0.0-rc.4
@schematics/angular               9.0.0-rc.4
@schematics/update                0.900.0-rc.4
rxjs                              6.5.3
typescript                        3.6.4
webpack                           4.41.2

Anything else relevant? This works correctly when you don’t add the @Component decorator to the base class, but due to changes in IVY, @Inputs and other variables marked with Angular decorators no longer work in base classes without the @Component or @Directive decorators applied to the base class

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
alxhubcommented, Dec 5, 2019

There’s a fair bit going on here, but the crux of this issue is that this is working as intended. Let me break it down a bit.

The need for a decorator on the base class.

This is a known change for Ivy, and there is an ng update migration that does this for you in most cases. In general Ivy requires a top-level decorator on any base class that:

  1. has @Input() or other Angular decorators on its fields, or
  2. declares a constructor that is inherited into a class that is decorated.

The general recommendation in this case is to add @Directive() with no arguments (i.e. no selector). Such an “abstract” directive does not need to be declared in an NgModule.

Constructor DI validity

This is where your error actually comes from. The constructor in the base class declares a parameter with type string, which is not a type that the DI system knows how to inject. It doesn’t matter whether the parameter is @Optional or not - the compiler does not know what token to even ask for in the first place, so it produces this error.

In this case, because you’re using an @Component decorator on the base class, the compiler is treating it like a concrete type that the framework might have to create itself, which is why you get a hard error.

If you switch to an abstract @Directive() as mentioned above, this behavior changes. If the constructor is not DI compatible, the compiler instead generates a DI factory that will error at runtime if ever invoked. This means it’s your responsibility when extending from the abstract directive to declare a DI-compatible constructor (and thus call super() explicitly), as if you inherit the broken constructor, it will crash at runtime.

0reactions
angular-automatic-lock-bot[bot]commented, Jan 6, 2020

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

Read more comments on GitHub >

github_iconTop Results From Across the Web

typescript - Angular 9 do abstract classes for services need the ...
If your base classes don't use Angular features you don't need an Angular decorator. In Angular 9, this requirement is optional; but don't ......
Read more >
Missing @Directive()/@Component() decorator migration
This migration adds an empty @Directive() decorator to undecorated base classes that: Use Angular features; Are extended by directives or components.
Read more >
Learning the Basics - Gradle User Manual
Gradle will look at the base url location for the POM and the JAR. If the JAR can't be found there, the extra...
Read more >
abc — Abstract Base Classes — Python 3.11.1 documentation
A class that has a metaclass derived from ABCMeta cannot be instantiated unless all of its abstract methods and properties are overridden.
Read more >
Groovy Language Documentation
reserved keywords can be used for method names if quoted def "abstract"() { true } ... If you use optional typing by using...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found