Typescript模块工厂模式

Typescript module factory pattern

本文关键字:模式 工厂 模块 Typescript      更新时间:2023-09-26

在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?

我不确定我是否完全理解这种常见模式。你把module对象从一个模块传递到另一个模块?所有其他类型的对象都是这样传递的(例如app, db),但我不喜欢传递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有自己的模式。

您可以做的一件事是在顶部导入函数,然后稍后调用它。TypeScript使用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;
}

接口允许在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中经常看到的那种模式。

希望这能给你一些启发

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

let module = factpryMethod('module');

我知道这个问题相当老了,但我在将现有的JS项目转换为使用这种模式的TypeScript时遇到了同样的问题。

不必在接口中预先定义模块定义,我们可以使用ReturnType帮助器来获得函数返回类型的类型定义!

模块可能是这样的:

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>;

我们可以这样使用它:

import initModule, { SampleModule } from './factory';
const newModule: SampleModule = initModule(1, 2);
newModule.functionA(); // 1
newModule.functionB(); // 2

说真的,TypeScript有多酷?:)