如何在具有 angular 注入参数的打字稿中创建新对象

How to create new object in typescript having angular-injected parameters

我有一个打字稿class,其中构造函数我有一个普通参数和一个angular-注入参数:

export class MyClass {
    private translation:string;

    public static $inject = ['$filter'];
    constructor(name:string, $filter: ng.IFilterService) {
        this.translation = filter('translate')('code').toString();
    }
}

如果我现在想创建一个对象,我该怎么做?

new MyClass('myname'); //won't compile because there are too few parameters
new MyClass('myname', filter); //makes no sense since I want to inject it

即使我写 $filter? 它也不会工作,因为它无法识别范围并且它将是未定义的。

那么,我怎样才能让它工作?

我的方法

假设我在另一个 class 中,我想在其中创建一个 MyClass 对象。下面的代码可以工作,但我不喜欢在这个 class 中也必须注入 $filter 的想法,因为它不需要它。

export class ClassUsingTheOtherClass {
    private filter:ng.IFilterService;

    public static $inject = ['$filter'];
    constructor($filter: ng.IFilterService) {
        this.filter = $filter;
    }

    doThings() {
        var clazz = new MyClass('myName', this.filter);
    }
}

我宁愿这样调用 var clazz = new MyClass('myName'); 并让 $filter 作为依赖项自动注入到 MyClass 中。这可能吗?

export class MyClass {

    public static $inject = ['$scope'];
    constructor(name:string, $scope?: ng.IScope) {
        //do things...                
    }
}

通过修改 class,使 $scope 后面有一个问号,您告诉编译器 $scope 是一个可选参数。

现在您可以 运行 new MyClass('myname');.

我认为您遗漏了一些有关 DI(注入)的信息。关键是不要手动创建任何依赖项。相反,总是解决它们并使用 Angular 这是在构造函数中自动完成的。唯一的例外应该是 class 具有 0 angular 依赖关系并且没有像纯 entity/data class.

这样的行为的限制

Typescript 还为您提供了定义接口(契约)的能力。您应该创建它们并将它们用作参考点,而不是直接使用 class 类型。这将允许您更改行为甚至定义(提供松耦合)。这也使单元测试更容易。

您的示例可以这样重写:

export interface IMyService{
   doThing:()=>void;
}

// should be registered with angular with service name 'ngMyService'
export class MyClass implements IMyService {
    private translation:string;

    public static $inject = ['$filter'];
    constructor($filter: ng.IFilterService) {
        this.translation = $filter('translate')('code').toString();
    }

    doThing() : void {
        // something
    }
}

export class ClassUsingTheOtherClass {

    public static $inject = ['ngMyService'];
    constructor(private myService: IMyService) {
    }

    doThings() {
        this.myService.doThing();
    }
}

现在用名称 ngMyService 向 angular 注册 MyClass 并向 angular 注册 ClassUsingTheOtherClass。您在哪里注册它们取决于它们的用途(控制器、服务、工厂、过滤器等)。

当 angular 创建 ClassUsingTheOtherClass 的实例时,它会自动将 MyClass 注入到构造函数中。 MyClass 反过来会自动将 $filter 注入到构造函数中。

最后我发现 MyClass 中的字符串 name 参数没有用,所以我删除了它。你将永远无法注入这个,因为你不能注册一个带有 angular 的字符串来注入。您可以在类型本身中对名称进行硬编码,也可以提供一个 name 属性 / 可以由 MyClass 的用户设置的字段(将字段添加到接口 IMyService) 但在我看来这打破了高内聚规则。