我可以这样获得对象的名称:
let name = obj.prototype.constructor.name;
但是我想做的是获取通用Angular服务中通用类型的名称。
@Injectable({
providedIn: 'root'
})
export class MyService<T> {
private _value: T;
constructor(){}
//... other methods
private error(error: any)
{
console.log(`Error for service type: ${_value.prototype.constructor.name}`)
}
}
_value.prototype.constructor.name
不起作用,类型T不存在原型。
我见过专门针对打字稿的帖子,指出只有在构造函数采用类型参数的情况下才有可能,因为一旦转译的类型声明被删除,因为它们在javascript中不存在,便成为可能。
随着angular通过依赖注入创建此服务时,传递该类型的正确方法是什么,以便可以以允许我将名称读取为字符串的方式进行实例化?
我在这篇文章中看到了:How to get name of generic type T inside service in Angular
它说要使用此功能:
function createInstance<T>(type: new() => T): T {
return new type();
}
但是我看不到我应该如何在上面的角度服务中使用此功能。
如何在服务中获取字符串?
答案 0 :(得分:2)
您不能通过类型检查的方式来执行此操作。
如果您可以使用typeof T
。
// doesn't work
@Injectable({
providedIn: 'root'
})
export class MyService<T> {
private _value: T;
private _type: typeof T = T;
^^^^^ 'T' refers to a type but is being used as a value
private error() {
console.log(`Error for service type: ${this._type.prototype.constructor.name}`)
}
}
您可以进行一些调整以使此工作有效。在继续之前,请意识到您将丢失一些类型检查。
typeof T
替换为Function
(对于类,基本上是any
)@Injectable()
装饰器... Angular不会帮助您找到实际的类型。重构后:
export class MyService<T> {
private _value: T;
private _type: Function;
constructor(type: Function) {
this._type = type;
}
private error() {
console.log(`Error for service type: ${this._type.prototype.constructor.name}`)
}
}
基本用法如下:
let myStringService = new MyService<String>(String);
只是为了证明您丢失了类型检查,这将编译没有错误:
class HeckinBamboozled { }
let myNumberService = new MyService<Number>(HeckinBamboozled);
现在,您有两个选择可以使用DI进行此操作。最简单的方法是创建和提供派生类型。
@Injectable({ providedIn: 'root' })
export class MyStringService extends MyService<String> {
constructor() {
super(String);
}
}
其他服务很容易消耗掉它。
@Injectable()
export class OtherService {
constructor(private stringService: MyStringService) {
}
}
第二种方法更新颖,并且使用注入令牌。
export const STRING_SERVICE = new InjectionToken<MyService<String>>('My String Service', {
providedIn: 'root',
factory: () => new MyService<String>(String)
});
但是它更难食用。
@Injectable()
export class OtherService {
constructor(@Inject(STRING_SERVICE) private stringService: MyService<String>) {
}
}
实际上,它比第一个选项的类型安全性差。这样编译不会出错。
@Injectable()
export class OtherService {
constructor(@Inject(STRING_SERVICE) private stringService: MyService<HeckinBamboozled>) {
}
}