我可以像这样获取对象的名称:
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 的原型(prototype)不存在。
我看过 typescript 特定的帖子,其中指出只有当构造函数采用该类型的参数时才可能实现这一点,因为一旦转译的类型声明就会被删除,因为它们在 JavaScript 中不存在。
由于 Angular 是通过依赖注入(inject)创建此服务,所以传递类型的正确方法是什么,以便可以以允许我将名称读取为字符串的方式实例化?
我在这篇文章中看到:How to get name of generic type T inside service in Angular
它说使用这个功能:
function createInstance<T>(type: new() => T): T {
return new type();
}
但是我不知道应该如何使用与上面的 Angular 服务相关的这个函数。
如何获取服务中的字符串?
最佳答案
您无法通过类型检查的方式使其工作。
如果您可以使用 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) {
}
}
第二个选项更奇特,并且使用注入(inject) token 。
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>) {
}
}
关于angular - 获取通用 Angular 服务中的类型名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53798262/