angular - 获取通用 Angular 服务中的类型名称

标签 angular typescript

我可以像这样获取对象的名称:

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/

相关文章:

angular - 可观察与 asObservable()?

javascript - typescript 符号异步函数作为类型/接口(interface)属性

Angular 2 : 404 error occur when I refresh through the browser

google-app-engine - 将基本的 Angular 2 应用程序部署到 Google App Engine

javascript - 从 DOM 调用服务函数 - Angular 2

javascript - 使用 .getElementsByClassName() 的 Typescript 返回类型

使用对象参数的 TypeScript 条件返回类型和默认值

datetime - xrmquery.update -> 更新 crm 日期字段

Angular2 动画 '* => void' 过渡未使用 *ngFor 组件项激活

forms - Angular 2 : 'ngFormModel' since it isn't a known native property