0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AngularでInterface指定でDIしたかったのでChatGPTに聞いてみた

Posted at

Angular+SpringBootでWebアプリを実装することが多く、どちらもDIコンテナを備えてますが、
・Angular -> 実クラスを指定してDI
・SpringBoot -> Interfaceを指定してDI
として通常実装しています。
ただ、依存性の注入。という意味では利用側はInterfaceだけを意識して、実装クラスの解決をDIコンテナに任せたく、AngularでもInterfaceを指定してDIができないものかと思っていました。

Angular界隈では常識なのかもしれませんが、私は知らなかったのでChatGPTに聞いてみました。
(今更流行りにのって。。。)

ChatGPTとの会話

image.png
image.png
image.png
image.png
image.png
image.png
image.png

いやこいつ天才か!?

すごすぎるだろ。。。知りたかったことが2,3分で知れました。。。
ただし、ChatGPTは嘘を教えることもあるので、実際にやってみます

実装

インタフェース

service.interface.ts
export interface ServiceInterface {
  show: () => void;
}

実装クラス(prod)

prod.service.ts
import { Injectable } from '@angular/core';
import { ServiceInterface } from './service.interface';

@Injectable({
  providedIn: 'root',
})
export class ProdService implements ServiceInterface {
  constructor() {}

  show() {
    console.log('This is ProdService.');
  }
}

実装クラス(test)

test.service.ts
import { Injectable } from '@angular/core';
import { ServiceInterface } from './service.interface';

@Injectable({
  providedIn: 'root',
})
export class TestService implements ServiceInterface {
  constructor() {}

  show() {
    console.log('This is TestService.');
  }
}

よし、これであとはapp.module.tsのprovidersにfactoryを設定して、利用クラス側でDIすればOK。
prodで動かした場合はprod.service.ts、それ以外はtest.service.tsがDIされて動く想定。

ん、、、、エラー出てるやんけ。。。
image.png

provideにinterfaceは指定できないな。。。ChatGPTに嘘つかれたか。。。
調べてみた感じやり口としては二通りありそう。
1.Interfaceを継承するabstract classを実装して、abstract classをprovideに指定する
2.Interfaceに紐づくInjectionTokenを生成し、それをprovideに指定する

好みですが、2の方法で対処してみます。

app.module.ts
import { environment } from 'src/environments/environment';
import { ProdService } from './service/prod.service';
import { TestService } from './service/test.service';
import { ServiceInterface } from './service/service.interface';

// environmentでインスタンス化するクラスを変えていく
const myFactory = () => {
  return environment.production ? new ProdService() : new TestService();
};

// ServiceInterfaceに紐づくInjectionTokenを生成する
export const SERVICE_TOKEN = new InjectionToken<ServiceInterface>(
  'service.interface'
);

@NgModule({
  declarations: [AppComponent, CustomTooltipComponent, CustomTooltipDirective],
  imports: [BrowserModule, AppRoutingModule, OverlayModule],
  providers: [
    {
      // 生成したInjectionTokenをprovideに指定する
      provide: SERVICE_TOKEN,
      useFactory: myFactory,
    },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

あとは利用クラスを書くのみ

app.component.ts
import { Component, Inject } from '@angular/core';
import { SERVICE_TOKEN } from './app.module';
import { ServiceInterface } from './service/service.interface';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  title = 'angular-sample';
  // DIする際に@InjectでInjectionTokenを指定する
  constructor(@Inject(SERVICE_TOKEN) sv: ServiceInterface) {
    sv.show();
  }
}

@InjectでInjectionToken指定するのが、個人的には微妙ですね。。。
なんとかならんのかな。その場合はabstract class方式で実装するのが良いのでしょうか。

いざ、稼働確認

ng serve --configutaion production

image.png

ng serve

image.png

おおおおおおおおおおおおおおおおおおおお、すげええええええ!!
紆余曲折ありましたが、やりたいことはできました。ChatGPTすごい!!!

使ってみて思いましたが、AIに仕事奪われるとか、もうおれらの価値なんて、、、、ってネガティブな感じではなく、ChatGPTを利用しまくってもっともっと成長するぜって気になりました。
とにかく、情報の収集効率がほんとに良くて、案Aと案Bどっちが良いかな?みたいな相談にも使えたりするのでChatGPTからの回答自体が非常に勉強になることが多いです。

ただ、今回みたいにガセ情報もあるので、もう一段踏み込んで考えたり、ググって裏どりするのが重要ですね。
また、相談系もこちらの誘導尋問的なこともできるし、ChatGPTが忖度した回答してくるときもあるので、案Aと案Bのメリットデメリットを聞くとか、公平性を意識した質問が良いんですかね。

以上です。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?