我有一个Logger
班
class Logger {
private logs = [];
public log = (message: string) => {
// append `message` to logs
};
public complete = () => {
// log all `logs` to the console
};
}
和我想强制使用complete
方法。
这意味着必须在某个时刻调用complete
。 (具体来说,它应该是将被调用的最后一个方法)
如果永远不会调用complete
,则会引发错误。
const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');
l.complete();
l.complete()
将被调用,一切都很好✔️
const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');
l.complete()
将永远不会被调用,因此应该有一个错误✖️
const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');
if (someVariable) {
l.complete();
}
l.complete()
可能不会被调用,请抛出一个错误✖️
const l = new Logger();
l.log('start processing');
doSomething();
l.log('processing has been finished');
if (someVariable) {
l.complete();
} else {
l.complete();
}
l.complete()
肯定会被调用,一切都很好✔️
const l = new Logger();
l.log('start processing');
await doSomething();
l.log('processing has been finished');
l.complete();
l.complete()
将被异步调用,一切都很好✔️
答案 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时要小心,因为异步日志记录可能不会出现在“日志”窗格中,但是应该出现在您的实际控制台日志中)。
好的,希望能有所帮助;祝你好运!