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
Angular 6 service with interface
提问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.service和SessionStorage.service。我想将 sessiontorage 注入到身份验证服务中。这可以通过:
constructor(private sessionStorage: SessionStorage) {
}
No problem there. But for Object Orientated purposes I want to have an interface
above 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 useClass
in 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 deps
or 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}]