[英]Typescript module factory pattern
There is a well-known approach in node.js to leverage the module factory pattern. node.js 中有一种众所周知的方法来利用模块工厂模式。 For, example:
例如:
m.js js
function factoryMethod(module) {
// doing some stuff and returning object initialized with module parameter
}
app.js应用程序.js
var o = require('./m')(module);
// using o
How can I do the same in typescript.我如何在打字稿中做同样的事情。 Actually, creating m.ts is not a problem:
其实创建m.ts不是问题:
m.ts m.ts
function factoryMethod(module: NodeModule): any {
// doing some stuff
}
export = factoryMethod;
But how should I use import syntax to use this module factory method like in javascript?但是我应该如何使用导入语法来像在 javascript 中一样使用这个模块工厂方法?
import {factoryMethod} from './m.ts'
let module = factpryMethod('module');
I'm not sure I quite get this common pattern. 我不确定我是否会得到这种通用模式。 You're passing the
module
object from one module into another? 您要将
module
对象从一个模块传递到另一个模块? All kinds of other objects are passed around like this, (eg app
, db
), but I don't like the idea of passing around the module
object. 各种各样的其他对象都是这样传递的(例如
app
, db
),但是我不喜欢传递module
对象的想法。 I'd be tempted to call it an anti-pattern. 我很想称其为反模式。 Surely the
module
object should stay in the module to which it belongs. 当然,
module
对象应该留在它所属的模块中。
That said, if you just want to import and call a function on the same line, you could do this using Node's require()
function, just like regular JavaScript. 就是说,如果您只想在同一行上导入并调用一个函数,则可以使用Node的
require()
函数来完成此操作,就像常规JavaScript一样。 Let's say you are passing an Express app
rather than module
. 假设您要传递Express
app
而不是module
。
const o = require('./m')(app);
However, you lose type-safety with this; 但是,您将因此失去类型安全性。
o
will be of type any
. o
将为any
类型。 You would have to explicitly define the type of o
. 您将必须明确定义
o
的类型。
const o: Module = require('./m')(app);
This is a bit silly. 这有点傻。 In fact,
Module
is likely to be defined in the module you are requiring anyway, so it is likely also self-defeating. 事实上,
Module
可能是你需要反正模块中进行定义,所以它也有可能弄巧成拙。 My suggestion is this. 我的建议是这个。 Don't expect to use the same patterns you are used to in plain JS in TypeScript, which has its own patterns.
不要期望使用与TypeScript中的普通JS相同的模式,后者具有自己的模式。
One thing you could do is import the function at the top, and then call it later. 您可以做的一件事是在顶部导入该函数,然后再调用它。 TypeScript uses ES2015-style modules , which don't allow you to import a function and call it on the same line.
TypeScript使用ES2015样式的模块 ,这些模块不允许您导入函数并在同一行上调用它。 You will have to rewrite both files, since
export =
is not valid in ES2015. 您将必须重写两个文件,因为
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;
}
The interface allow type inference in app.ts
, which is an improvement of a kind. 接口允许在
app.ts
进行类型推断,这是一种改进。
// app.ts
import {factoryMethod} from './m';
// ...
let o = factoryMethod(app);
But this is still very silly. 但这仍然很愚蠢。 We don't need to define an interface and all that nonsense.
我们不需要定义接口和所有的废话。 Instead, we can use a class .
相反,我们可以使用class 。 Classes are very often the answer in TypeScript, and you'll find that most patterns in TypeScript involve them.
在TypeScript中,类通常是答案,并且您会发现TypeScript中的大多数模式都涉及到它们。
// m.ts
export class Module {
constructor(private app: Express.Application) { }
cache: string[];
someMethod(): Promise<Express.Response> {
// do something with this.app
}
}
And then in app.ts
然后在
app.ts
import {Module} from './m';
// ...
let o = new Module(app);
Now we don't have to worry about interfaces and all that. 现在,我们不必担心接口等所有问题。 The class itself is a type.
类本身是一种类型。 This is quite a bit different from what you are likely to see in a typical Node app, but it is the sort of pattern you find all the time in TypeScript.
这与典型的Node应用程序中可能会看到的内容有很大不同,但这是您一直在TypeScript中发现的那种模式。
Hopefully that gives you some ideas. 希望能给你一些想法。
I know this question is fairly old but I came across the same issue when converting an existing JS project to TypeScript that makes use of this pattern.我知道这个问题已经很老了,但是在将现有的 JS 项目转换为使用这种模式的 TypeScript 时,我遇到了同样的问题。
Instead of having to pre-define the module definition in an interface we can use the ReturnType
helper to get a type definition of the return type of a function!不必在接口中预先定义模块定义,我们可以使用
ReturnType
助手来获取函数返回类型的类型定义!
This is what the module might look like:这是模块可能的样子:
function initModule(arg1: number, arg2: number) {
function functionA() {
return arg1;
}
function functionB() {
return arg2;
}
return {
functionA,
functionB,
};
}
export default initModule;
export type SampleModule = ReturnType<typeof initFactory>;
And here is how we could use it:这是我们如何使用它:
import initModule, { SampleModule } from './factory';
const newModule: SampleModule = initModule(1, 2);
newModule.functionA(); // 1
newModule.functionB(); // 2
Seriously, how cool is TypeScript?说真的,TypeScript 有多酷? :)
:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.