Разрешить универсальный параметр в Angular Generic Service - PullRequest
3 голосов
/ 12 марта 2019

У меня есть структура классов, где мне нужно BaseModel и много ChildModels.Примерно так:

// BaseModel type

import { Injectable } from '@angular/core';

@Injectable()
export class BaseModel { 
    constructor() {
    }

    public _instanceUrl(): string {
        return '';
    };

    public url(): string {
        return 'BASE_URL_' + this._instanceUrl();
    };
}

// ChildModel type

import { BaseModel } from './base-model';
import { Injectable } from '@angular/core';

@Injectable()
export class ChildModel extends BaseModel {
    constructor() {
        super();
    }

    public _instanceUrl(): string {
        return "CHILD_URL";
    }
}

// BaseService type

import { Injectable} from '@angular/core';
import { BaseModel } from '../models/base-model';

@Injectable()
export class BaseService<T extends BaseModel> {

    private url: string; 
    constructor(private childInstance: T) { 
    } 

    public getUrl() {
        return this.childInstance.url();
    }
}

Вот моя реализация AppModule:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
    AppRoutingModule,
    ServicesModule
  ],
  providers: [BaseService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Здесь я использовал сервис

import { Component } from '@angular/core';
import { BaseService } from './modules/services/base-service/base-service.service';
import { ChildModel } from './modules/services/models/child-model';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent {
  title = 'angular-test';
  preventAbuse = false;

    constructor(private baseService: BaseService<ChildModel>) {
    }

    testHttp() {
        console.log(this.baseService.getUrl());
    }
}

Мне нужно знать, возможно ли для Angular предоставить правильный тип T для конструктора BaseService (в данном случае ChildModel).В настоящее время я получаю сообщение об ошибке, в котором говорится, что он не может предоставить параметры construtor.

Uncaught Error: не удается разрешить все параметры для BaseService: (?).

Если я удаляю параметр из конструктора BaseService, служба создается ОК.Проблема не в том, чтобы вводить BaseService, проблема в том, чтобы вводить параметр конструктора BaseService типа T. Кроме того, у меня могут быть сотни дочерних классов, поэтому я бы хотел не предоставлять их все.Тем не менее, я не уверен, что это возможно.

Я использую последнюю версию Angular и Typescript

Angular CLI: 7.3.4
Angular: 7.2.7
typescript: 3.2.4

Вот ссылка на Stackblitz

1 Ответ

1 голос
/ 12 марта 2019

Простым решением является использование фабричного шаблона, как это предложено Внедрение универсальных услуг в Angular

providers: [{
 provide: 'baseService',
 useFactory: (childModel: ChildModel) => (new BaseService<ChildModel>(childModel)),
 deps: [ChildModel]
}]

constructor(@Inject('baseService') private baseService: BaseService<ChildModel>) { 
  console.log(baseService.getUrl()); // output "BASE_URL_CHILD_URL"
}
...