質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.75%

  • AngularJS

    558questions

    AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

  • TypeScript

    301questions

    TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

  • Angular2

    163questions

  • import

    90questions

    自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

  • Angular

    78questions

AngularでCan't resolve all parameters for のエラー。Interfaceが使えない?Angularのバグ?

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 603

ringoing888

score 5

 実現したいこと

Angularのとあるクラスにて、同一インターフェースを実装した複数の実装クラスを引数として受け取れるようにしたいと思っています。もう少し具体的な所で言うとDAOが使うデータアクセスサービスを、HTTP経由のAPI形式やデータベースへの直接接続など、提供される形式に応じて入れ替えられるドライバークラスを実装しようとしています。

 発生している問題

Chromeのデベロッパー ツール上のコンソールで以下のエラーが出てます。

compiler.js:485 Uncaught Error: Can't resolve all parameters for dao: (?).

 at syntaxError (compiler.js:485)
    at CompileMetadataResolver._getDependenciesMetadata (compiler.js:15662)
    at CompileMetadataResolver._getTypeMetadata (compiler.js:15497)
    at CompileMetadataResolver._getInjectableMetadata (compiler.js:15477)
    at CompileMetadataResolver.getProviderMetadata (compiler.js:15837)
    at eval (compiler.js:15748)
    at Array.forEach (<anonymous>)
    at CompileMetadataResolver._getProvidersMetadata (compiler.js:15708)
    at CompileMetadataResolver.getNgModuleMetadata (compiler.js:15276)
    at CompileMetadataResolver.getNgModuleSummary (compiler.js:15114)

 該当のソースコード

  • driver.ts
    インターフェースの宣言
export interface Driver {
}
  • dao.ts
    daoは引数にインターフェースでdriverを実装した実装クラスを受取る.
import { Injectable } from '@angular/core';
import { Driver } from './driver';

@Injectable()
export class dao {
    constructor(private accesor: Driver)
    {  /* 初期化処理 */ }
}
  • webapidriver.ts
    driverインターフェースの実装クラス
import { Injectable } from '@angular/core';
import { Driver } from './driver';

@Injectable()
export class WebAPIDriver implements Driver {
    constructor() {}
}
  • service.ts
    daoにdriverインターフェースを実装したWebAPIDriverをセット
import { Injectable } from '@angular/core';
import { WebAPIDriver } from './webapidriver';
import { DAO } from './dao';

@Injectable()
export class service{

    constructor() {
    /* WebAPIDriverはdirverインターフェースを実装 */
        var dao = new DAO(new WebAPIDriver());
    }
}

 試したこと

  • Issuesを参考にpolyfills.tsの以下の行をコメントアウトしてみたが、エラーは同じで発生場所が変わっただけでした。
  import 'core-js/es7/reflect';
  • この記事でインスタンス生成時に、コンストラクタ引数に何渡せば良いかわらなくなってるという事でdaoのコンストラクタにInjectデコレータを付けてみました。あたりまえですが、WebAPIDriverを指定したら普通に動作しました。(やりたい事は出来てませんが)
import { Injectable, Inject } from '@angular/core';
                    //↑付け足す
import { Driver } from './driver';
import { WebAPIDriver } from './WebAPIdriver';
// ↑ 付け足す

export class dao {
    constructor(
        @Inject(WebAPIDriver) private accesor: Driver
             //↑付け足す
    )
    {  /* 初期化処理 */ }
}
  • この記事この記事で循環参照?(or circular imports)の問題とあったのでとりあえず分散してたファイルを一箇所に集約してservice.ts内に全てのコードを集約してみましたがこれも駄目でした。ま~当たり前かもしれないですが。。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

TypeScriptのインターフェースはコンパイル時に消える情報ですので、JavaScript上に残らず、DIのトークンとしては使えません。ですので、 

@Injectable()
export class dao {
    constructor(private accesor: Driver)
    {  /* 初期化処理 */ }
}

というコンストラクタは@Injectableが適用できません。

このような場合は引数の型ではなくInjectionTokenを使うのが一般的です。

// InjectionTokenの宣言
export const DRIVER = new InjectionToken<Driver>('driver');

@NgModule({
  // ...
  providers: [
    // InjectionTokenに対して実体クラスを割り当てる
    { provide: DRIVER, useClass: WebAPIDriver },
  ]
})
export class AppModule {}
@Injectable({ providedIn: 'root' })
export class dao {
    // DRIVERをトークンとしてDriver型の引数をとる
    constructor(@Inject(DRIVER) private accesor: Driver)
    {  /* 初期化処理 */ }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.75%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • AngularJS

    558questions

    AngularJSはオープンソースのJavaScriptフレームワークです。ブラウザ上で動作するウェブアプリケーションの開発にMVCアーキテクチャを取り入れることを目的としています。

  • TypeScript

    301questions

    TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

  • Angular2

    163questions

  • import

    90questions

    自身のプラットフォーム・プログラム・データセットに対して、外部ソースを取り込むプロセスをimportと呼びます。

  • Angular

    78questions