Angular如何使用类型令牌(Type-Token)注册依赖注入?
解决Angular依赖注入中类型令牌(Type-Token)的报错问题
问题核心
TypeScript的接口仅存在于编译阶段,编译后会被完全移除,而Angular依赖注入需要运行时存在的实体作为令牌,因此直接用接口MyService作为注入令牌会触发报错'MyService' only refers to a type, but is being used as a value here.
正确方案一:用抽象类替代接口
抽象类在编译后会保留运行时实体,可直接作为类型令牌使用,是最简洁的解决方案。
- 定义抽象类
MyService
export abstract class MyService { abstract getHeroes(): Observable<Hero[]>; // 按需定义其他公共方法签名 }
- 让业务服务继承抽象类
@Injectable() export class HeroService extends MyService { getHeroes(): Observable<Hero[]> { // 原有业务实现逻辑 } } @Injectable() export class NewHeroService extends MyService { getHeroes(): Observable<Hero[]> { // 新的业务实现逻辑 } }
- 组件构造函数注入
@Component({ selector: 'app-hero-list', templateUrl: './hero-list.component.html' }) export class HeroListComponent { constructor(private service: MyService) {} }
- 注册依赖(模块/组件级别)
@NgModule({ declarations: [HeroListComponent], providers: [ { provide: MyService, useClass: HeroService } // 切换服务仅需替换此处的类名 ] }) export class HeroModule {}
正确方案二:使用InjectionToken(保留接口场景)
若必须保留接口定义,可通过InjectionToken创建运行时令牌:
- 定义
MyService接口
export interface MyService { getHeroes(): Observable<Hero[]>; }
- 创建注入令牌
import { InjectionToken } from '@angular/core'; export const MY_SERVICE = new InjectionToken<MyService>('MyService');
- 业务服务实现接口
@Injectable() export class HeroService implements MyService { getHeroes(): Observable<Hero[]> { // 业务实现逻辑 } } @Injectable() export class NewHeroService implements MyService { getHeroes(): Observable<Hero[]> { // 业务实现逻辑 } }
- 组件中注入(需配合
@Inject装饰器)
import { Inject } from '@angular/core'; @Component({ selector: 'app-hero-list', templateUrl: './hero-list.component.html' }) export class HeroListComponent { constructor(@Inject(MY_SERVICE) private service: MyService) {} }
- 注册依赖
@NgModule({ declarations: [HeroListComponent], providers: [ { provide: MY_SERVICE, useClass: HeroService } // 切换服务仅需替换useClass的值 ] }) export class HeroModule {}
总结
- 优先选择抽象类方案:代码更简洁,无需额外装饰器,符合Angular依赖注入的常规实践
- 若需保留接口,使用**
InjectionToken+@Inject**组合实现类型令牌注入
内容的提问来源于stack exchange,提问作者Murmulodi
相关产品推荐
相关产品推荐

