Custom InjectionToken in Angular not functioning properly with Ahead-of-Time compilation activated

Within my codebase, there exists the following constructor:

constructor(env: Env, private logger: Logger,
  @Inject(MockEndpoints.TOKEN) @Optional() 
  private endpoints: MockEndpoints[]) {
    // ...
}

It functions as intended when utilized with the JIT compiler. However, when the AOT compiler is enabled, it triggers a build error:

ERROR in : Can't resolve all parameters for MockBackendInterceptor in /path/mock-backend.interceptor.ts: ([object Object], [object Object], ?).

The structure of the token object is outlined below:

export interface MockEndpoints {
  handle(req: HttpRequest<any>): HttpResponse<any>;
}

export namespace MockEndpoints {
  export const TOKEN: InjectionToken<MockEndpoints[]> = 
    new InjectionToken<MockEndpoints[]>('MockEndpoints');
}

I was under the impression that I followed the documentation guidelines precisely. Any suggestions or insights? ;)

UPDATE (in response to Gunter's comment): The endpoints are registered within the same module:

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: MockBackendInterceptor, multi: true },
    { provide: MockEndpoints.TOKEN, useClass: MockBackupService, multi: true },
    { provide: MockEndpoints.TOKEN, useClass: MockConfigurationService, multi: true }
  ]
})
export class MockBackendModule { }

Answer №1

At last, I uncovered the root cause.

Special thanks to members yurzui and Günter Zöchbauer for their insightful comments that led me to identify the issue.

SOLUTION

Only if the constant token is defined within a namespace, the type parameter of the InjectionToken (for example, MockEndpoints in this scenario) cannot be an interface. The solution was as simple as changing it to an abstract class instead.

export abstract class MockEndpoints {
  handle(req: HttpRequest<any>): HttpResponse<any>;
}

export namespace MockEndpoints {
  export const TOKEN: InjectionToken<MockEndpoints[]> = 
    new InjectionToken<MockEndpoints[]>('MockEndpoints');
}

Furthermore, extracting the TOKEN constant from the namespace proved to be even more straightforward.

export interface MockEndpoint {
  handle(req: HttpRequest<any>): HttpResponse<any>;
}

export const MOCK_ENDPOINT = new InjectionToken<MockEndpoint[]>('MockEndpoints');

It's worth noting that having the same name for both the namespace and the interface (like in the case of MockEndpoints) did not have any significance. It only caused issues when declaring the token constant inside a namespace with a different name, thus incompatible with the interface as a type parameter.

Alternatively, using a plain string token instead of the InjectionToken interface also resolved the problem.

This peculiar behavior was observed exclusively during AOT compilation. There were no complications with JIT compilation in either case.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Submit information by utilizing' content-type': 'application/x-www-form-urlencoded' and 'key': 'key'

Attempting to send data to the server with a content-type of 'application/xwww-form-urlencode' is resulting in a failure due to the content type being changed to application/json. var headers= { 'content-type': 'applica ...

"Trying to create a new project with 'ng new xxx' command resulted in error code -4048

Whenever I execute 'ng new projectName' in vs code, I encounter the following issue. ng new VirtualScroll ? Would you like to add Angular routing? Yes ? Which stylesheet format would you like to use? SCSS [ http://sass-lang.com ] CREATE Vir ...

Why Injecting the Kernel into a Service in Symfony 2 is a Mistake

I'm trying to retrieve the current app environment in my service. I discovered that I can obtain it from the kernel, but there are concerns about injecting the kernel directly. Can someone clarify why this is seen as a poor practice? Wouldn't ...

How to resolve the issue of any data type in Material UI's Textfield

I am seeking clarity on how to resolve the TypeScript error indicating that an element has an 'any' type, and how I can determine the appropriate type to address my issue. Below is a snippet of my code: import { MenuItem, TextField } from '@ ...

Angular 4+ causing input/textarea tag malfunction on ASP NET 2.1 server

Has anyone else come across this issue before? I tried searching extensively on Google but could not find any solutions, even after experiencing input crashes. I am working on a project with Angular 6 page served by ASP.NET Core 2.1. Everything was functi ...

Positioning the box at the exact middle of the screen

I'm trying to center an item on the screen using material ui, but it's appearing at the top instead of the middle. How can I fix this? import * as React from 'react'; import Box, { BoxProps } from '@mui/material/Box'; functio ...

Angular: Implementing ngIf within ngFor for Dynamic Content Display

I'm working on dynamically populating a list with conditional rendering for each list item, where the condition can be changed by user input. For instance: app.component.ts private check = true; private some = [ {name: 'ABC', cond ...

ngx-bootstrap Date Range Picker displaying current and previous month on open

The ngx-bootstrap Date range picker usually displays the current month and the next month. However, I would like to customize it to show the current month and the previous month instead. For example, if the current month is December, it should display Nove ...

Angular 5 update issue: NgReduxRouter provider not found error

Since upgrading to Angular 5, I have been encountering an error message related to my store module. The current version of Angular-Redux is now at 7.1.0 An unhandled Promise rejection has occurred: StaticInjectorError(AppModule)[StoreModule -> NgRed ...

Ways to modify the text color of a dropdown button upon clicking by leveraging ViewChild and ElementRef techniques

I'm attempting to change the color of text in my dropdown menu button after it's clicked using @Viewchild and elementRef. However, the method I've tried doesn't seem to be working as expected. <div class="dropdown"> ...

Struggling with Angular Components?

Although I have come across discussions on the topic such as this one at How to import component into another root component in Angular 2, my issue remains unresolved. I am facing a similar dilemma. My current challenge involves Angular-Cli - after succe ...

A reflective key error has occurred because the token was not properly defined!

My current setup includes Angular version 2.4.4. However, I encountered an issue when trying to declare a service resolver and register it in both the component module and router. import { Injectable } from '@angular/core'; import { Resolve, Ac ...

Dealing with code in Angular when transitioning to a different component

I have an Angular component that displays data and includes a button called "Go to Dashboard". I want to implement a feature where the user can either click on this button to navigate to the dashboard or have the application automatically redirect them aft ...

Angular 2 sidebar icons appearing vertically instead of in a row

Greetings! I've been struggling for hours to display a sidenav using Angular 2, with links listed as rows. Here is what my current setup looks like: https://i.sstatic.net/fmmAR.jpg Here is the code I've been working on: <md-sidenav-containe ...

best practices for choosing items from a dropdown menu using Angular

I have a dropdown list displaying existing tags/chips created by users in the past. However, I'm having an issue where when I select a tag from the dropdown list, it doesn't show up in my input field (similar to the Chart tag currently). I am abl ...

The value of req.headers('Authorization') has not been defined

I'm experiencing difficulty with my code as the token is coming back as undefined. Here is the frontend section: export const fetchUser = async (token: any) => { const res = await axios.post('/user/getuser', { headers ...

What sets typescript apart when using a getter versus a regular function?

Imagine having a class with two methods declared for exclusive use within that class. // 1. private get something() { return 0; } // 2. private getSomething() { return 0; } While I am familiar with getters and setters, I'm intrigued to know if ther ...

Searching for an entity that may contain fetchable connections

Utilizing my REST API allows me the option to fetch relations based on specific requests. For instance, a basic call like GET /payment-request will return the following simplified payload: [ { "id": "01FBPR3K0RYBCRGCBWEC2AK30P", ...

The status code 0 was returned for the null URL

I am facing an issue with my Ionic 3 application that is using the same API as my previous versions of Ionic apps. After logging in, I encountered the following error: Response with status: 0 for URL: null I have researched online and found suggestion ...

What is the best way to incorporate a @types module into a TypeScript file that is not already a module?

Setting the Stage: In the process of shifting a hefty ~3,000 line inline <script> from a web-page to a TypeScript file (PageScripts.ts) to be utilized by the page through <script src="PageScripts.js" defer></script>. This script entails ...