【问题标题】:Can I create a TypeScript class within a function and refer to its parameters?我可以在函数中创建一个 TypeScript 类并引用它的参数吗?
【发布时间】:2014-08-28 12:10:10
【问题描述】:

例如在 angularJS 中,我可以使用以下构造:

myApp.factory('MyFactory', function(injectable) {
    return function(param) {
        this.saySomething = function() {
            alert("Param=" + param + " injectable=" +injectable);
        }
    };
});

以后可以这样使用:

function(MyFactory) {
    new MyFactory().saySomething();
}

当传递给方法factory 的函数被调用时,参数injectable 被锁定,并且将进一步可用于MyFactory 的新实例,而无需再次指定该参数。

现在我想使用 TypeScript,显然我想指定我的 MyFactory 是新的,并且有一个函数 saySomething。我怎么能优雅地做到这一点?

我可以这样写:

class MyFactory {
    constructor(private injectable, private param) {}
    saySomething() {
        alert(...);
    }
}
myApp.factory('myFactory', function(injectable) {
    return function(param) {
        return new MyFactory(injectable, param);
    }
});

但这会改变 API:

function(myFactory) {
    myFactory().saySomething();
}

我想知道它是否可以更优雅,因为我喜欢“新”如何非常清楚地表示创建了一个新的唯一对象,而这个对象的创建是工厂的全部目的。

【问题讨论】:

标签: angularjs typescript


【解决方案1】:

** 编辑:TypeScript >= 1.6 支持class expressions,您现在可以编写如下内容:

myApp.factory(injectable: SomeService) {
  class TodoItem {
    ...
  }
}

** 原答案:

我有同样的问题:使用 AngularJS 和 ES5,我喜欢依赖注入而不是污染构造函数,并且能够使用 new 关键字。

使用 ES6,您可以将类包装在函数中,TypeScript 尚不支持此功能(请参阅 https://github.com/Microsoft/TypeScript/issues/307)。

这是我所做的(MyFactory 现在是 todo 应用程序中的类 TodoItem 以更相关):

class TodoItem {
  title: string;
  completed: boolean;
  date: Date;

  constructor(private injectable: SomeService) { }

  doSomething() {
    alert(this.injectable);
  }
}

class TodoItemFactory() {
  constructor(private injectable: SomeService) { }

  create(): TodoItem {
    return new TodoItem(this.injectable);
  }

  // JSON from the server
  createFromJson(data: any): TodoItem {
    var todoItem = new TodoItem(this.injectable);
    todoItem.title = data.title;
    todoItem.completed = data.completed;
    todoItem.date = data.date;
    return todoItem;
  }
}

// In ES5: myApp.factory('TodoItem', function(injectable) { ... });
myApp.service('TodoItemFactory', TodoItemFactory);


class TodosCtrl {
  // In ES5: myApp.controller('TodosCtrl', function(TodoItem) { ... });
  constructor(private todoItemFactory: TodoItemFactory) { }

  doSomething() {
    // In ES5: var todoItem1 = new TodoItem();
    var todoItem1 = this.todoItemFactory.create();

    // In ES5: var todoItem2 = TodoItem.createFromJson(...)
    var todoItem2 = this.todoItemFactory.createFromJson(
      {title: "Meet with Alex", completed: false}
    );
  }
}

这不如 ES5 和函数优雅(并且不使用 TypeScript 类是不行的):-/

我想写什么:

@Factory
@InjectServices(injectable: SomeService, ...)
class TodoItem {
  title: string;
  completed: boolean;
  date: Date;

  // No DI pollution
  constructor() { }

  saySomething() {
    alert(this.injectable);
  }

  static createFromJson(data: string): TodoItem {
    ...
  }
}

@Controller
@InjectFactories(TodoItem: TodoItem, ...)
class TodosCtrl {
  constructor() { }

  doSomething() {
    var todoItem1 = new TodoItem();

    var todoItem2 = TodoItem.createFromJson({title: "Meet with Alex"});
  }
}

或者用函数:

myApp.factory(injectable: SomeService) {
  class TodoItem {
    title: string;
    completed: boolean;
    date: Date;

    // No constructor pollution
    constructor() { }

    saySomething() {
      alert(injectable);
    }

    static createFromJson(data: string): TodoItem {
      ...
    }
  }
}

myApp.controller(TodoItem: TodoItem) {
  class TodosCtrl {
    constructor() { }

    doSomething() {
      var todoItem1 = new TodoItem();

      var todoItem2 = TodoItem.createFromJson({title: "Meet with Alex"});
    }
  }
}

【讨论】:

  • 从 TypeScript 1.6 开始,支持类表达式。
【解决方案2】:

我可以写这样的东西

这就是我的工作

我可以在函数中创建一个 TypeScript 类吗

不,它需要位于文件的顶层或模块中。仅供参考,如果能够在函数内创建它,则信息将被锁定在该函数内,并且至少 type 信息将无用。

【讨论】:

    【解决方案3】:

    实例化多个 MyFactory 实例的原因是什么?您不想将工厂的单个实例注入到您的依赖代码中吗?

    我认为使用您提供的类声明后,注入后实际上看起来像这样:

    function(myFactory) {
        myFactory.saySomething();
    }
    

    如果你真的需要将构造函数传递给你的依赖代码,那么我认为你将不得不放弃 TypeScript 类,因为它们不能在函数内部定义,这意味着你无法创建一个关闭注入到此类函数中的变量。

    您总是可以选择只使用 TypeScript 中的函数而不是类。仍然可以获得强大的打字优势,并且可以在其上调用“新”,因为它在一天结束时仍然是一个 .js 函数。这是一个稍微更 TypeScriptiffied 的版本:

    myApp.factory('MyFactory', (injectable: ng.SomeService) => {
    
        return (param: string) => {
    
            return {
                saySomething: () {
                    alert("Param=" + param + " injectable=" +injectable);
                }
            };
        };
    });
    

    【讨论】:

      猜你喜欢
      • 2012-10-30
      • 2015-06-20
      • 2011-10-06
      • 1970-01-01
      • 2011-06-13
      • 2018-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多