Angular DI classType: Type<MyClass> is not a constructor

Viewed 22

So I try to use angular dependency injection in ngOnInit instead of constructor. I found some examples of this using a factory provider, but things does not quite work...

I get a reference to a

let myClassType: Type<MyClass> = ....

object that I can instantiate myself using

let myClassInstance = new myClassType(http)

but when I try to set up DI to allow me the same using DI I seem to fail... For some reason I get error messages in the console stating that myClassType on the return line of the myClassFactory function isn't a constructor, but since it's possible to manually create a instance using the same code elseware...

On my Component I use this constructor:

constructor(@Inject(MyClass) private _myClassFactory: (myClassType: Type<MyClass>) => MyClass

My understanding is that this pattern should be possible in components ngOnInit:

let myClassInstance: MyClass = this._myClassFactory(myClassType);

and my model has this:

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        HttpClientModule,
        AppRoutingModule
    ],
    providers: [
        myClassProvider
    ],
    bootstrap: [ AppComponent ]
})

and my MyClass.ts looks like this:

@Injectable()
export abstract class MyClass {
    constructor(http: HttpClient) {}
}

export function myClassFactory(myClassType: Type<MyClass>, http: HttpClient): MyClass {
    return new myClassType(http);
};

export let myClassProvider = { 
    provide: MyClass,
    useFactory: myClassFactory,
    deps: [HttpClient]
};

The reason I want to do this unusual pattern is because I want to be able to create an instance of MyClass using parameters passed from a http call, so they will not be available when the component is created. I have simplified my example as much as possible.

1 Answers

I am so mad... Turns out a did a slight misstake, shocker..... I got it working by replacing this:

export function myClassFactory(http: HttpClient, myClassType: Type<MyClass>): MyClass {
    return new myClassType(http);
};
export let myClassProvider: Provider = { 
    provide: MyClass,
    useFactory: myClassFactory,
    deps: [HttpClient]
};

With this:

export let myClassProvider: Provider = {
    provide: MyClass,
    useFactory: (http: HttpClient) => (myClassType: Type<MyClass>) => new myClassType(http),
    deps: [ HttpClient ]
};

At first I didn't see the difference but notice that the first attempt sets useFactory as a function taking two parameters... The second attempt sets useFactory to a function taking one parameter where that function returns a new function that takes one parameter also!

It seems that since parameters are optional in js (and angular translates to js) that DI calls the provider function at startup, but since no parameter was added it only had the http reference. This meant that the variable myClassType was undefined, and of course that won't do as a constructor!

Related