When trying to extend a class from a class in a node_modules
the typescript compiler throws a error saying:
Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.
This only happens when the base class is from a node_module
.
The base class looks like:
import {Observable} from "rxjs/Observable";
export abstract class TestBase<T> {
request(options: any):Observable<T> {
return Observable.throw(new Error('TestBase is abstract class. Extend it and implement own request method'));
}
}
Subclassing it in a project:
import {Observable} from "rxjs/Observable";
import {TestBase} from "@org/core";
class SocketResponse {
}
class Socket {
request(): Observable<SocketResponse> {
return new Observable.of(new SocketResponse());
}
}
export class Sub extends TestBase<SocketResponse> {
request(options:any):Observable<SocketResponse> {
return new Socket().request();
}
}
If the base class (TestBase
) is moved from the node_module
to the project it self and change the import to look like
import {TestBase} from "./base";
The error disappears.
Is this due to that the compiles creates the types in different scopes for each module? I'm completely lost here.
Update:
This seems to only happen when linking the node_modules
with npm link
.
Seems like one possible workaround for the moment is to instead of returning a type in the base class to return a interface.
More information can be found here:
https://github.com/Microsoft/TypeScript/issues/6496
https://github.com/ReactiveX/rxjs/issues/1744
I just came across a very similar issue while developing a custom module for a project. I'm not 100% sure we were having the same problem, but it looks pretty close.
I would suggest deleting your node_modules
folder and reinstalling all your dependencies.
rm -rf node_modules/
npm cache clean
npm install
That solved it for me.
The module I was developing had an abstract class that the main project was trying to extend. However when trying to compile the main project, the compiler would throw the same error you are getting.
After a bit of digging around, I noticed NPM would complain about an UNMET PEER DEPENDENCY
when installing my module into my project. When looking inside the node_modules
of the project, I noticed that my module had another node_modules
folder nested inside of it with some dependencies that it shared with the main project.
I'm not certain about this, but I think NPM thought the module was expecting different version of dependencies it shared with the main project.
So the abstract class inside the module was referencing Observable from its own nested node_modules
folder while the main project was referencing Observable from the top level node_modules
folder.
This other questions provided some insight for me when trying solve my problem:
Why does npm install say I have unmet dependencies?
If there are multiple node_modules folders you have to add a path mapping in the host app's tsconfig. Just map @rxjs/* to the root node_modules/rxjs/*. Then everything works fine.
You can add a path mapping in your tsconfig.json to map the rxjs in your dependency to the one in your node_modules folder:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"rxjs": ["node_modules/rxjs"]
}
}
more documentation is available at the Typescript site
I got same issue.
I have following catalog structure (angular2 project)
angular
|
---- common_files
|
----- package.json
|
----- index.ts
|
----- catalog1
|
---- package.json
|
---- some_file_with_service_model_comopnent.ts
|
---- index.ts - this is regular barrel file
|
----- catalog2
|
---- app1
|
------ package.json
|
---- apps
|
------ package.json
In my common I have definied objects and services:
export class ItemBase {}
esport class SomeType extends ItemBase {}
export class ItemServiceBase {
public getItems():Observable<ItemBase> {
//do something
}
}
export class SomeService extends ItemServiceBase {
//some specific operations can go here
}
In my apps I was using items from common as follows:
import { SomeType, SomeTypeService } from "warehouse-system/products-settings";
class AttributeTypesComponent {
private myValues : Observable<SomeType[]>;
private service : SomeTypeService;
constructor(){
this.service = new SomeTypeService();
this.myValues = <Observable<SomeType[]>> this.service.getItems();
}
}
This were causing compilation issues:
ERROR in [at-loader] src/app/some_file.ts:22:47
Type 'Observable<ItemBase[]>' cannot be converted to type 'Observable<SomeType[]>'.
Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.
After investigation I changed type of myValues
but it still doesn't solve problem. Compilation issues changed to:
ERROR in [at-loader] src/app/some_file.ts:22:47
Type 'Observable<SomeType[]>' cannot be converted to type 'Observable<SomeType[]>'.
Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.
The final solution (workaround)
What solved my problem, was "rewriting" observable on the app side:
this.myValues = Observable.create(subscriber => {
this.service.getItems().subscribe(items => subscriber.next(items));
});
This is not really nice way to solve it. In my opinion this problem is caused by a bug in npm/typescript/observables. But untill the problem is not solved on the typescript devs side, you can use this workaround as solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With