typescript - 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()
将被异步调用,一切都很好✔️
解决方案
据我所知,编译器没有提供执行此操作的方法。我之前没有看到与此功能完全相同的副本,但它让我想起了一个类似的(参见microsoft/TypeScript#21388)要求制作它,以便您可以标记一个类方法,以便需要子类覆盖来调用超类方法。细节与您的问题不同,但它们都要求编译器在特定情况下未调用特定方法时发出警告。而且,据我所知,至少在 TypeScript 3.8 中,TypeScript 都没有办法做到这一点。所以你的问题的答案是“这是不可能的”。
也许不同的方法会起作用?与其要求Logger
实例的用户作为最后一个方法调用,不如只在类似 Promise 的回调complete()
中将一个实例交给用户,然后在回调完成时调用呢?这是“这是你的。请在你完成后打电话”和“告诉我你想用你的 做什么,然后我会在完成后打电话”之间的区别。这是一个可能的实现:Logger
complete()
Logger
complete()
Logger
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
实例调用的,然后complete()
调用它的方法。
在您上面的示例中,现在无法制定 2 和 3(甚至 4)。complete()
无论如何都会调用该方法。示例 1 如下所示:
Logger.invoke(l => {
l.log('start SYNC processing');
doSomething();
l.log('SYNC processing has been finished');
})
示例 5 如下所示:
Logger.invoke(async l => {
l.log('start ASYNC processing');
await doSomething();
l.log('ASYNC processing has been finished');
});
您可以验证它们是否都有效(使用 TypeScript Playground 时要小心,因为异步日志记录可能不会出现在“日志”窗格中,但它们应该出现在您的实际控制台日志中)。
好的,希望有帮助;祝你好运!
推荐阅读
- python - 重新运行单元格要求用户输入时,Jupyter Notebook 冻结
- multithreading - 如何检查后台作业是否已完成但在 PowerShell 中保持 Windows 窗体响应
- r - devtools::document 错误:认为应该将部分功能描述作为包导入
- reactjs - React-router-dom:链接编译失败
- c - 从函数中调用 malloc 和 realloc 会产生意想不到的结果
- html - 将 CSS 转换保持在其结束状态
- python - 如何让python3.8访问python3.6的模块?
- css - 如何使我的图像在响应时保持其方形形状并且不设置大量媒体查询?
- c++ - 移除 In Bounds Array 元素上的越界警告
- python - 我怎样才能让我的敌人子弹攻击更好?