打字稿-如何强制调用类方法? (使方法强制)

时间:2020-04-05 11:53:41

标签: typescript

目标

我有一个Logger

class Logger {
  private logs = [];

  public log = (message: string) => {
    // append `message` to logs
  };

  public complete = () => {
    // log all `logs` to the console
  };
}

我想强制使用complete方法

这意味着必须在某个时刻调用complete。 (具体来说,它应该是将被调用的最后一个方法) 如果永远不会调用complete,则会引发错误。

示例

(1)

const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');
l.complete();

l.complete()将被调用,一切都很好✔️

(2)

const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');

l.complete()将永远不会被调用,因此应该有一个错误✖️

(3)

const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');
if (someVariable) {
  l.complete();
}

l.complete()可能不会被调用,请抛出一个错误✖️

(4)

const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');
if (someVariable) {
  l.complete();
} else {
  l.complete();
}

l.complete()肯定会被调用,一切都很好✔️

(5)

const l = new Logger();
l.log('start processing');
await doSomething();
l.log('processing has been finished');
l.complete();

l.complete()将被异步调用,一切都很好✔️

1 个答案:

答案 0 :(得分:2)

据我所知,编译器没有提供执行此操作的方法。我之前没有看到过与该功能完全相同的内容,但是它让我想起了类似的功能(请参见microsoft/TypeScript#21388),因此您可以标记一个类方法,以便需要子类重写来调用超类方法。详细信息与您的问题不同,但是它们都要求编译器警告在特定情况下是否未调用特定方法。而且,据我所知,至少在TypeScript 3.8中,无法在TypeScript中执行任何操作。因此,您所提出的问题的答案是“这不可能”。


也许其他方法可行?而不是要求您的Logger实例的用户调用complete()作为最后一个方法,而是如果您仅将一个Logger实例的用户交给类似Promise的回调,而< em> you 回调完成后呼叫complete()吗?区别在于“这里是您的Logger。完成后请致电complete()”和“告诉我您想使用Logger做些什么,然后我打电话给{ {1}}完成后”。这是一个可能的实现:

complete()

因此class Logger { private constructor() { } private logs: string[] = []; public log(message: string) { this.logs.push(message) }; private complete() { this.logs.forEach(l => console.log(l)); }; public static invoke<R>(cb: (logger: Logger) => R): R { const logger = new Logger(); const r = cb(logger); if (r instanceof Promise) { const t = r.then(x => (logger.complete(), x)) as any as R; return t; } else { logger.complete(); return r; } } } 构造函数和Logger方法都是私有的。某人可以对complete()进行的唯一操作是对其调用Logger,这需要进行回调。在处理同步和异步回调方面存在一些折衷,因为我想您希望同步调用同步回调。但是在两种情况下,都使用私有invoke()实例调用回调,然后再调用其Logger方法。

在上面的示例中,现在无法公式化2和3(甚至4)。 complete()方法无论如何都会被调用。示例1如下所示:

complete()

和示例5看起来像这样:

Logger.invoke(l => {
    l.log('start SYNC processing');
    doSomething();
    l.log('SYNC processing has been finished');
})

您可以验证它们是否都可以正常工作(使用TypeScript Playground时要小心,因为异步日志记录可能不会出现在“日志”窗格中,但是应该出现在您的实际控制台日志中)。

Playground link to code


好的,希望能有所帮助;祝你好运!

相关问题