Reputation: 8731
I want to create a generic api service in order to make model-related services easier to create:
export abstract class ModelService<T> {
constructor(protected apiService: ApiService) {
//ApiService is a service that wraps Http and adds signature , auth and serialization.
}
public getAll(): Observable<T[]> {
return this.apiService.get<T[]>(this.modelClass, this.baseUrl);
}
}
then, I will create my service that manages model Foo
:
@Injectabe()
export class FooService extends ModelService<Foo>{
}
But when I call fooService.getAll().subscribe(...);
I get an error saying that apiService
is undefined (cannot get property 'get' of undefined).
So the fix is to add a constructor in FooService
like this:
constructor(api: ApiService) {
super(api);
}
But problem is that it's not dev-friendly, nothing tells you to do so and since FooService
extends ModelService
, it should have the same constructor and therefore the same dependencies.
Is there any way to inherit dependency?
PS: I already tried to add @Injectable()
to ModelService
, same error.
EDIT: tsconfig.json
:
{
"compilerOptions": {
"baseUrl": "",
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": [
"es6",
"dom"
],
"mapRoot": "./",
"module": "es6",
"moduleResolution": "node",
"outDir": "../dist/out-tsc",
"sourceMap": true,
"target": "es5",
"typeRoots": [
"../node_modules/@types"
]
}
}
package.json
:
"dependencies": {
"@angular/common": "2.2.1",
"@angular/compiler": "2.2.1",
"@angular/core": "2.2.1",
"@angular/forms": "2.2.1",
"@angular/http": "2.2.1",
"@angular/platform-browser": "2.2.1",
"@angular/platform-browser-dynamic": "2.2.1",
"@angular/router": "3.2.1",
...
...
},
"devDependencies": {
"@angular/compiler-cli": "2.2.1",
...
...
}
Upvotes: 2
Views: 400
Reputation: 223104
For child class that doesn't introduce extra dependencies and doesn't need its own constructor
it is
@Injectable()
export abstract class ModelService<T> {...}
export class FooService extends ModelService<Foo>{
}
@Injectable()
decorator is needed for parent class (if it uses type annotation and not @Inject
). No @Injectable()
decorator is needed for child class.
For children classes that may have their own dependencies and thus need own constructors the dependencies should be explicitly passed to super
(see the other answer). In JavaScript, rest operator and @Inject
may be used to skip some tautology, but for TypeScript it is safe to enumerate all constructor parameters explicitly.
Upvotes: 2
Reputation: 658057
The constructor needs to repeat the dependencies and then passed to the super class using super(...)
@Injectabe()
export class FooService extends ModelService<Foo>{
constructor(apiService: ApiService) {
super(apiService);
//ApiService is a service that wraps Http and adds signature , auth and serialization.
}
}
This is not an Angular2 requirement or limitation, that's how constructors work in TypeScript.
Upvotes: 5