typescript 带接口的 Angular 6 服务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51174859/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:30:55  来源:igfitidea点击:

Angular 6 service with interface

angulartypescriptservicedependency-injectionangular6

提问by Mr.wiseguy

I am building an application with Angular (6.0.7) and I am trying to create a service with the new:

我正在使用 Angular ( 6.0.7)构建一个应用程序,并且我正在尝试使用新的服务创建一个服务:

@Injectable({
  providedIn: 'root'
})

But how can I type an injection with an Interface?

但是如何使用接口输入注入?



The problem

问题

I have 2 services, Authentication.serviceand SessionStorage.service. I want to inject the sessionstorage into the authentication service. That can be done via:

我有 2 个服务,Authentication.serviceSessionStorage.service。我想将 sessiontorage 注入到身份验证服务中。这可以通过:

constructor(private sessionStorage: SessionStorage) {
}

No problem there. But for Object Orientated purposes I want to have an interfaceabove this service (so that I can implement both localstorage service as sessionstorage service). Thus it is only logical that I want to type the injected class with the interface, but this cannot be done the same way Angular 5 and lower does it.

没有问题。但是出于面向对象的目的,我想要一个interface高于此服务的服务(以便我可以将本地存储服务实现为会话存储服务)。因此,我想用接口键入注入的类是合乎逻辑的,但这不能像Angular 5 和更低版本那样完成

So how can I type the injection into this global service with my interface?

那么如何使用我的界面将注入输入到这个全局服务中呢?



I've tried

我试过了

The Angular service typings describe an InjectableProvider, but this does not match any of the parameters of the siblings of InjectableProvider, so this gives a compiler (and tslint) error.

Angular 服务类型描述了InjectableProvider,但这与 的兄弟姐妹的任何参数都不匹配InjectableProvider,因此这会产生编译器(和 tslint)错误。

@Injectable({
  providedIn: 'root'
}, {provide: IStorageService, useClass: SessionStorage})

回答by jenson-button-event

This can be done with InjectionToken, which is a replacement for the obsolete OpaqueToken

这可以用 来完成InjectionToken,它是过时的替代品OpaqueToken

export const AuthenticationProvider = new InjectionToken(
  "AuthenticationProvider",
  { providedIn: "root", factory: () => new CognitoAuthenticationProvider() }
);

...

@Injectable()
export class CognitoAuthenticationProvider implements IAuthenticationProvider {

...

@Injectable({
  providedIn: "root"
})
export class AuthenticationService {
  constructor(
    @Inject(AuthenticationProvider)
    private authenticationProvider: IAuthenticationProvider,
    private http: HttpClient
  ) {}

回答by k0zakinio

I used something like the following to solve this

我用类似下面的东西来解决这个问题

app.module.ts

app.module.ts

providers: [
  { provide: AlmostInterface, useClass: environment.concrete }
  ...
]

AlmostInterface.ts

几乎接口.ts

export abstract class AlmostInterface {
   abstract myMethod();
}

MyConcrete.ts

MyConcrete.ts

export class MyConcrete implements AlmostInterface {
   myMethod() { ... }; // implementation
}

export class MyConcreteAlternative implements AlmostInterface {
   myMethod() { ... }; // implementation
}

environment.ts

环境.ts

export const environment = {
  production: false,
  concrete: MyConcreteAlternative
};

environment.prod.ts

环境.prod.ts

export const environment = {
  production: true,
  concrete: MyConcrete
};

回答by SirDieter

I think you can't use typescript interfaces for dependency injection as typescript interfaces don't existat runtime (only for typesafety at compile time).
I would suggest using an abstract classfor it.

我认为你不能使用 typescript 接口进行依赖注入,因为typescript 接口在运行时不存在(仅用于编译时的类型安全)。
我建议为它使用抽象类

EDIT: It seems you can use useClassin the firstparameter of @Injectable, not as a second like your example. Combining that with @k0zakinio's answer results in:

编辑:看来您可以useClass在@Injectable的第一个参数中使用,而不是像您的示例那样使用第二个参数。将其与@k0zakinio 的答案相结合会得到:

@Injectable({
  providedIn: 'root',
  useClass: environment.concrete,
  deps: []
})
export abstract class SessionStorage { }

It also seems you need to declare your dependencies via depsor inject, checkout this github issue. I hope this time my answer is of more help.

似乎您还需要通过deps或声明您的依赖项inject,请查看此github 问题。我希望这次我的回答对您有所帮助。

回答by eduPeeth

You can use something like -

你可以使用类似的东西 -

[{ provide: InterfaceName, useClass: ClassName}]