打字稿模块工厂模式

时间:2016-06-29 14:39:45

标签: javascript node.js typescript

node.js中有一个众所周知的方法来利用模块工厂模式。例如:

m.js

function factoryMethod(module) {
  // doing some stuff and returning object initialized with module parameter
}

app.js

var o = require('./m')(module);
// using o

我怎样才能在打字稿中做同样的事情。实际上,创建m.ts不是问题:

m.ts

function factoryMethod(module: NodeModule): any {
  // doing some stuff
}

export = factoryMethod;

但是我应该如何使用导入语法来使用像javascript一样的模块工厂方法?

2 个答案:

答案 0 :(得分:1)

import {factoryMethod} from './m.ts'


let module = factpryMethod('module');

答案 1 :(得分:1)

我不确定我是否会得到这种常见模式。您是否将module对象从一个模块传递到另一个模块?所有类型的其他对象都是这样传递的(例如appdb),但我不喜欢传递module对象的想法。我很想把它称为反模式。当然module对象应该保留在它所属的模块中。

也就是说,如果您只想在同一行导入并调用函数,可以使用Node require()函数执行此操作,就像常规JavaScript一样。我们假设您传递的是快递app而不是module

const o = require('./m')(app);

然而,你失去了类型安全性; o的类型为any。您必须明确定义o的类型。

const o: Module = require('./m')(app);

这有点傻。实际上,Module可能会在您要求的模块中定义,因此它可能也会弄巧成拙。我的建议是这样的。不要期望在TypeScript中使用与普通JS相同的模式,它有自己的模式。

您可以做的一件事是在顶部导入函数,然后再调用它。 TypeScript使用ES2015-style modules,它不允许您导入函数并在同一行上调用它。您必须重写这两个文件,因为export =在ES2015中无效。

// m.ts

interface Module {
  // properties, methods, etc.
}

export function factoryMethod(app: Express.Application): Module {
  let module = {};
  // Initialize module methods, properties, etc.
  return module;
}

界面允许app.ts中的类型推断,这是一种改进。

// app.ts

import {factoryMethod} from './m';

// ...

let o = factoryMethod(app);

但这仍然非常愚蠢。我们不需要定义界面和所有废话。相反,我们可以使用。类通常是TypeScript的答案,你会发现TypeScript中的大多数模式都涉及它们。

// m.ts

export class Module {

  constructor(private app: Express.Application) { }

  cache: string[];

  someMethod(): Promise<Express.Response> {
    // do something with this.app
  }

}

然后在app.ts

import {Module} from './m';

// ...

let o = new Module(app);

现在我们不必担心接口和所有这些问题。类本身就是一种类型。这与您在典型的Node应用程序中可能会看到的有很大不同,但它是您在TypeScript中一直找到的那种模式。

希望能给你一些想法。