如何在Angular 5服务中获取泛型类型T的名称并创建工厂方法
在Angular 5服务中使用泛型T创建实例并获取类型名称的解决方案
这个问题其实是TypeScript泛型的典型局限——泛型类型在运行时会被擦除,所以你没法直接通过T获取类型信息或者实例化它。下面给你具体的解决办法:
问题根源
TypeScript的泛型是编译时的语法糖,编译成JavaScript后,所有泛型类型都会被移除。这就导致:
- 你声明的
let type: new () => T;只是一个类型注解,并没有实际的赋值,所以typeof(type)返回undefined new T()会直接编译报错,因为运行时根本不存在T这个值
核心解决方案:传递构造函数引用
要在运行时获取泛型类型的信息并实例化,你需要手动传递该类型的构造函数引用(也就是类本身,因为在JS里类就是构造函数)。具体步骤如下:
- 在服务的构造函数(或方法)中添加一个类型为
new () => T的参数,用来接收T的构造函数 - 通过这个构造函数实例化对象,同时可以通过
构造函数.name获取类型名称
完整代码示例
@Injectable() export class SomeService<T> { someModel: T; constructor( protected userService: UserService, // 新增:接收T的构造函数 private modelConstructor: new () => T ) { const user = this.userService.getLocalUser(); // 实例化泛型类型T this.someModel = new this.modelConstructor(); // 获取类型名称 const typeName = this.modelConstructor.name; console.log(`当前泛型类型名称:${typeName}`); // 输出如"MyModel" // 检查实例类型(现在可以正常判断) console.log(this.someModel instanceof MyModel); // 正确返回true/false } // 可选:如果需要在方法中动态创建实例,也可以封装成方法 createNewModel(): T { return new this.modelConstructor(); } }
如何注入这个服务
因为现在服务需要额外的modelConstructor参数,你需要通过useFactory来提供服务实例:
在组件中注入
@Component({ selector: 'app-my-component', templateUrl: './my-component.component.html', providers: [ { provide: SomeService, // 工厂函数:传入依赖并创建服务实例 useFactory: (userService: UserService) => new SomeService<MyModel>(userService, MyModel), deps: [UserService] // 声明依赖的服务 } ] }) export class MyComponent { constructor(private someService: SomeService<MyModel>) {} }
在根模块中全局提供
如果需要在整个应用中使用该服务,也可以在AppModule的providers数组中配置:
@NgModule({ // ...其他配置 providers: [ { provide: SomeService, useFactory: (userService: UserService) => new SomeService<MyModel>(userService, MyModel), deps: [UserService] } ] }) export class AppModule {}
额外说明
- 如果你的泛型类需要接收构造参数,可以把构造函数类型改成
new (...args: any[]) => T,然后在实例化时传入对应参数 - 如果你需要支持多种泛型类型,可以创建多个不同的服务提供者,或者在方法中动态传递构造函数
内容的提问来源于stack exchange,提问作者Anonymous
相关产品推荐
相关产品推荐

