node_modules
のクラスからクラスを拡張しようとすると、TypeScriptコンパイラは次のエラーをスローします。
Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'.
これは、基本クラスがnode_module
からのものである場合にのみ発生します。
基本クラスは次のようになります。
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'));
}
}
プロジェクトでサブクラス化する:
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();
}
}
基本クラス(TestBase
)をnode_module
からプロジェクトに移動し、インポートをimport {TestBase} from "./base";
のように変更すると、エラーが消えます。
これは、コンパイルによって各モジュールの異なるスコープに型が作成されるためですか?ここで完全に迷ってしまいました。
更新:
これは、node_modules
をnpm link
とリンクする場合にのみ発生するようです。現時点で考えられる回避策の1つは、基本クラスで型を返す代わりにインターフェイスを返すことです。
詳細についてはこちらをご覧ください。
プロジェクトのカスタムモジュールを開発しているときに、非常によく似た問題に遭遇しました。私たちが同じ問題を抱えているとは100%確信していませんが、かなり近いように見えます。
node_modules
フォルダーを削除して、すべての依存関係を再インストールすることをお勧めします。
rm -rf node_modules/
npm cache clean
npm install
それで解決しました。
私が開発していたモジュールには、メインプロジェクトが拡張しようとしている抽象クラスがありました。ただし、メインプロジェクトをコンパイルしようとすると、コンパイラは同じエラーをスローします。
少し掘り下げた後、モジュールをプロジェクトにインストールするときにNPMがUNMET PEER DEPENDENCY
について文句を言うことに気付きました。プロジェクトのnode_modules
の内部を見ると、モジュール内に別のnode_modules
フォルダーがネストされており、いくつかの依存関係がメインプロジェクトと共有されていることがわかりました。
これについては定かではありませんが、NPMは、モジュールがメインプロジェクトと共有する異なるバージョンの依存関係を期待していると考えていたと思います。
そのため、モジュール内の抽象クラスは、ネストされた独自のnode_modules
フォルダーからObservableを参照し、メインプロジェクトは最上位のnode_modules
フォルダーからObservableを参照していました。
この他の質問は、私の問題を解決しようとするとき、私にいくつかの洞察を与えました:
同じ問題が発生しました。
次のカタログ構造があります(angular2プロジェクト)
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
私の共通では、オブジェクトとサービスを定義しました:
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
}
私のアプリでは、次のように共通のアイテムを使用していました。
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();
}
}
これにより、コンパイルの問題が発生していました: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>'.
調査後、myValues
のタイプを変更しましたが、それでも問題は解決しません。コンパイルの問題は次のように変更されました。
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>'.
最終的な解決策(回避策)
私の問題を解決したのは、アプリ側で観察可能な「書き換え」でした。
this.myValues = Observable.create(subscriber => {
this.service.getItems().subscribe(items => subscriber.next(items));
});
これは本当にそれを解決する良い方法ではありません。私の意見では、この問題はnpm/TypeScript/observablesのバグが原因です。ただし、TypeScript開発者側で問題が解決しない限り、この回避策を解決策として使用できます。
Node_modulesフォルダーが複数ある場合は、ホストアプリのtsconfigにパスマッピングを追加する必要があります。 @ rxjs/*をルートnode_modules/rxjs/*にマップするだけです。その後、すべてが正常に動作します。
この問題は、npmリンクを実行する場合にのみ発生します。
クライアントプロジェクトのtsconfig.jsonのcompilerOptionsにパスを追加します
"paths": { "rxjs/*": ["../node_modules/rxjs/*"]}
これは、rxjs依存関係からのパスを指定するので機能するはずです。
私は次のようなクレイジーなエラーを受け取っていました
Type 'Observable<MessageEvent>' cannot be converted to type 'Observable<MessageEvent>'
Property 'source' is protected but type 'Observable<T>' is not a class derived from 'Observable<T>'
そしてその理由はnpm link
(実際にはnpm i ../other-project
しかし、それはまったく同じことです。
私の回避策はちょっと浮気でした:
(stream as any as Observable<MessageEvent>)
LOL
Tsconfig.jsonにパスマッピングを追加して、依存関係のrxjsをnode_modulesフォルダーのrxjsにマッピングできます。
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"rxjs": ["node_modules/rxjs"]
}
}
より多くのドキュメントが TypeScriptサイト で利用可能です
Rxjsモジュールをリストした後:
npmリストrxjs
+-@ angular/cli @ 1.6.6 | +-@ angular-devkit/core @ 0.0.29 | |
-- [email protected] | +-- @angular-devkit/[email protected] | |
-- [email protected] |-- [email protected]
[email protected]
同じモジュールの2つのバージョンを見ることができます。私のプロジェクトでは、rxjsの下位バージョンが必要でした。 anglular/cliにはrxjsの上位バージョンが必要です。
以前は問題は発生していませんでしたが、突然同じ依存関係を持つすべてのプロジェクトが同じTS90010エラーをスローしました:
[at-loader]のエラー./src/main/webapp/app/admin/user-management/user-management-detail.component.ts:23:9 TS90010:タイプ 'Subscription'は、タイプ 'Subscription'に割り当てられません。この名前を持つ2つの異なるタイプが存在しますが、それらは無関係です。
プロパティ「_parent」は保護されていますが、タイプ「Subscription」は「Subscription」から派生したクラスではありません。
最後に、package.jsonのTypeScriptバージョンを2.6.2から2.9.2に更新し、すべてのエラーが消えました。