Why am I encountering difficulties with my property injection, as it is not injecting anything other than undefined

In my current TypeScript project utilizing inversify, I have set up a logger in my TYPES as TYPES.ILoggger. When I access the logger directly from my container, it functions as expected:

import {ILogger} from "./interfaces/ILogger";
import {TYPES} from "./interfaces/TYPES";
import container from "./kernel/inversify.config";

const loggerFromTheContainer: ILogger = container.get<ILogger>(TYPES.ILogger);
loggerFromTheContainer.info("I WILL LOG"); // this works

Everything seems to be properly configured.

Instead of accessing the container directly, I want to implement property injection. InversifyJS' README provides an example:

You can choose to use property injection instead of constructor injection so you don't need to declare the class constructor:

@injectable()
class Ninja implements Warrior {
    @inject(TYPES.Weapon) private _katana: Weapon;
    @inject(TYPES.ThrowableWeapon) private _shuriken: ThrowableWeapon;
    public fight() { return this._katana.hit(); }
    public sneak() { return this._shuriken.throw(); }
}

I attempted to follow this approach for injecting the logger.

However, when I try to inject the logger via property injection, it turns out to be undefined and I am unsure why:

@injectable()
class ShouldHaveLogger {
    @inject(TYPES.ILogger) private logger: ILogger;

    constructor() {
        this.logger.info("Hello World"); // the logger remains undefined here
    }
}

new ShouldHaveLogger();

This results in a generic

TypeError: Cannot read property 'info' of undefined

since this.logger is not being injected. How can I resolve this issue?

Answer №1

When utilizing property injection, the typical behavior involves allowing inversify to handle instance creation for you. However, there are instances where you may need to manually create the instance of ShouldHaveLogger yourself or have another library do it for you.

The documentation also mentions this scenario, which can be found here.

To achieve this, you will require inversify-inject-decorators, enabling you to inject the logger using @lazyInject.

You must configure lazyInject with your container, resulting in code that resembles the following:

import {injectable} from "inversify";
import getDecorators from "inversify-inject-decorators";
import {ILogger} from "./interfaces/ILogger";
import {TYPES} from "./interfaces/TYPES";
import container from "./kernel/inversify.config";   

const {lazyInject} = getDecorators(container);

@injectable()
class ShouldHaveLogger {
    @lazyInject(TYPES.ILogger) private logger: ILogger;

    constructor() {
        this.logger.info("I am working now");
    }
}

new ShouldHaveLogger();

Upon execution, the output will depend on your logger implementation:

2019-01-30T09:47:54.890Z - info: "I am working now"

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

Is the utilization of the React context API in NextJS 13 responsible for triggering a complete app re-render on the client side

When working with NextJS 13, I've learned that providers like those utilized in the React context API can only be displayed in client components. It's also been made clear to me that components within a client component are considered part of the ...

Angular array of considerable size

Dealing with a massive array of 30,000 items can be quite daunting, especially when it comes in as a stream using grpc-web. Currently, I'm fetching the data from grpc.client() and populating an array before displaying it using *ngFor. However, I' ...

Ensuring precise type inference in generic functions using the keyof keyword

I am facing a challenge in creating a versatile function that accepts an object and a key from a specific subset of keys belonging to the type of the object. These keys should correspond to values of a specified type. This is how I attempted to implement ...

There is an issue with the typings for React.createElement that is causing errors

Is it possible to implement React.createElement with TypeScript successfully? import React from "react"; type Props = { label: string; }; const Three: React.FC<Props> = (props: Props) => { return <div>{props.label}</div&g ...

Tips for configuring TypeScript in a monorepo to successfully compile private packages

I have configured a monorepo using turborepo that includes Nestjs for the backend and Nextjs for the frontend. To reuse prisma definitions, I separated them into their own package with its own tsconfig. In the index file of my database package where prism ...

Guide on accessing and manipulating local files using an Angular application

For my Angular 7 web app project, I'm looking to allow users to complete surveys and submit their responses. Since I don't have a database set up yet, I thought of storing the results in a local json file for now. Unfortunately, I'm facing d ...

Replace interface with a string

Is it possible to override an interface with a string in TypeScript? Consider this example: type RankList = "Manager" | "Staff" interface EmployeeList { id: string, name: string, department: string, rank: "Staff&q ...

What happens when the loading state does not update while using an async function in an onClick event?

I'm currently working on implementing the MUI Loading Button and encountering an issue with changing the loading state of the button upon click. Despite setting the state of downloadLoading to true in the onClick event, it always returns false. The p ...

Issues with hydrating React local storage hook in custom implementation within NextJS

Currently facing an issue while implementing the localstorage hook in NextJS. The error message I am encountering is: Error: Hydration failed because the initial UI does not match what was rendered on the server.. Any suggestions on what might be causing ...

Steps to resolve the issue of 'type is not assignable to any' while working with a member

I'm facing an issue with a code snippet like the one below: interface IFoo { bar: string; baz: number; } function f(foo: IFoo, name: 'bar' | 'baz', val: any) { foo[name] = val; // <<< error: Type 'any' i ...

Ensuring the structure of a model in a JSON array with Angular

While working with Angular, I have a model defined as follows: export interface MyModel { id: number; content: string; } In one of my services, I fetch JSON data that matches the attributes of MyModel. Here's an example: function getMyModel ...

There was a problem rendering the error view configuration callback for the RCTModalHostView component - it must be a function, but it was received as 'undefined'

Working on a mobile application in React Native, specifically using Expo SDK version ~51.0.18 for development. The project involves utilizing the Expo router to manage all routing within the app. Now, I'm looking to implement a new SDK called Lean t ...

Using ExpressJS with Typescript and NodeJS to serve static files is a powerful combination

Having trouble serving a static file uploaded using ExpressJS and NodeJS with Typescript as I'm encountering a 404 error. The file I need to access is located at ./src/data/uploads/test.txt, and I am attempting to reach it directly from a web browser ...

Implementing form validation for mandatory fields upon submission in Angular 17

There are several fields such as firstName and lastName that are marked as required on the backend. If the form is submitted without entering the firstName, an error is displayed in the Network Preview. Similarly, if the firstName is filled but the lastNam ...

The browser is throwing errors because TypeScript is attempting to convert imports to requires during compilation

A dilemma I encountered: <script src="./Snake.js" type="text/javascript"></script> was added to my HTML file. I have a file named Snake.ts which I am compiling to JS using the below configuration: {target: "es6", module: "commonjs"} Howeve ...

Exploring the wonders of HTTP requests through pure pipes in Angular 5

I've been working on a pipe that converts currency values from one to another by making an HTTP call. The idea is to pass in the source and destination currencies as parameters. @Pipe({ name: "currencyConverter" }) export class CurrencyConverterP ...

What is the best way to exempt a unique situation from a directive's operation?

While troubleshooting a bug related to search functionality on my page, I encountered an issue with the search component. The search feature is working correctly and returning the expected values. However, when I clear the search criteria, I noticed that t ...

What is the use of the mongoose $gt operator in an Express application built with

I am searching for users whose tokens have not yet expired. try { const user = await User.findOne({ resetToken: passwordToken, resetTokenExpiration: { $gt: Date.now() }, _id: userId, }); if (!user) { throw new NotFoundEr ...

Is there a way for me to maintain a consistent layout across all pages while also changing the content component based on the URL route in Next.js?

I'm currently working with Typescript and Next.js My goal is to implement a unified <Layout> for all pages on my website. The layout comprises components such as <Header>, <Footer>, <Sidenav>, and <Content>. Here is the ...

Adding Profile Photos to Authenticated User Accounts in Firebase / Ionic: A Step-By-Step Guide

I have thoroughly gone through the Firebase Docs on "Managing Users" for web along with watching their instructional video on YouTube. Despite following the code they provide, I am encountering an error message that states: "Property 'afAuth' do ...