没有 .bind(this) 的情况下,Mobx Flow 函数不会被 FlowType 检查类型
Mobx Flow functions are not type checked by FlowType without .bind(this)
当我们使用 MobX flow 修饰函数时,flowtype 认为 this
是 any 类型并且不进行类型检查。
class MyComponent extends Component<*> {
actionMethod = flow(function*(){
yield this.notAMethod();
});
}
但是,如果我们将它绑定到生成器,流会理解 this
的类型是 MyComponent
。
class MyComponent extends Component<*> {
actionMethod = flow((function*(){
yield this.notAMethod();
}).bind(this));
}
我的问题是我们如何确保这些方法经过类型检查。
- 是否有任何 linting 规则来确保我们正确绑定 (this)?
- 我们可以改进 mobx 类型吗?
- 这是流量问题吗?
this 是在 javascript 中动态导出的。所以流无法告诉你什么类型 this 将与静态分析。唯一的例外是当您将它显式绑定到此(就像您在第二种方法中所做的那样)或当您使用箭头函数时(但箭头函数不适用于 yield)。
考虑到这些知识,我将回答您的问题:
是否有任何 linting 规则来确保我们正确绑定(this)?
Flow在使用bind时告诉你类型。所以你不需要 linting 规则,因为类型是正确的。
我们可以改进 mobx 类型吗?
这不是 mobx 打字错误。 javascript 就是这样工作的。您无法判断 this 在运行时将是什么类型(除非您使用绑定或箭头函数或调用对象实例的方法)
这是流量的问题吗?
见上面的答案。
这里有一篇很长的 post 关于 javascript 中的 this 是如何工作的
我希望我能帮助澄清你的问题。
这是我在研究中找到的一个建议。试一试,让我知道它是否能解决问题。基本上他们手动分配了这个类型。
public fetchProjects = flow(function*(this: ProjectStore) {
this.projects = yield ProjectApi.get()
})
您的问题简化为创建自定义 lint 的能力。 Eslint 有一个很棒的库,可以用来编写你自己的 eslint 规则。您可以比较使用 https://astexplorer.net/
,使用和不使用 this
的代码之间的区别。然后你可以写一个看起来像这样的 eslint 规则(未测试):
// @no-flow
"use strict";
// Help from https://astexplorer.net/
module.exports.rules = {
"mobx-flow-requires-bind": context => ({
CallExpression: function(node) {
const ancestors = context.getAncestors();
const parent = ancestors.length > 0 && ancestors[ancestors.length - 1];
if (node.callee && node.callee.name === "flow") {
if (node.arguments.length === 1) {
const callee = node.arguments[0].callee;
if (!(callee && callee.property && callee.property.name === "bind")) {
context.report(node, "Calls to flow must be used with .bind");
}
}
}
}
})
};
您可以使用 this 教程将上述代码集成到您的存储库中。
当我们使用 MobX flow 修饰函数时,flowtype 认为 this
是 any 类型并且不进行类型检查。
class MyComponent extends Component<*> {
actionMethod = flow(function*(){
yield this.notAMethod();
});
}
但是,如果我们将它绑定到生成器,流会理解 this
的类型是 MyComponent
。
class MyComponent extends Component<*> {
actionMethod = flow((function*(){
yield this.notAMethod();
}).bind(this));
}
我的问题是我们如何确保这些方法经过类型检查。
- 是否有任何 linting 规则来确保我们正确绑定 (this)?
- 我们可以改进 mobx 类型吗?
- 这是流量问题吗?
this 是在 javascript 中动态导出的。所以流无法告诉你什么类型 this 将与静态分析。唯一的例外是当您将它显式绑定到此(就像您在第二种方法中所做的那样)或当您使用箭头函数时(但箭头函数不适用于 yield)。 考虑到这些知识,我将回答您的问题:
是否有任何 linting 规则来确保我们正确绑定(this)?
Flow在使用bind时告诉你类型。所以你不需要 linting 规则,因为类型是正确的。
我们可以改进 mobx 类型吗?
这不是 mobx 打字错误。 javascript 就是这样工作的。您无法判断 this 在运行时将是什么类型(除非您使用绑定或箭头函数或调用对象实例的方法)
这是流量的问题吗?
见上面的答案。
这里有一篇很长的 post 关于 javascript 中的 this 是如何工作的
我希望我能帮助澄清你的问题。
这是我在研究中找到的一个建议。试一试,让我知道它是否能解决问题。基本上他们手动分配了这个类型。
public fetchProjects = flow(function*(this: ProjectStore) {
this.projects = yield ProjectApi.get()
})
您的问题简化为创建自定义 lint 的能力。 Eslint 有一个很棒的库,可以用来编写你自己的 eslint 规则。您可以比较使用 https://astexplorer.net/
,使用和不使用 this
的代码之间的区别。然后你可以写一个看起来像这样的 eslint 规则(未测试):
// @no-flow
"use strict";
// Help from https://astexplorer.net/
module.exports.rules = {
"mobx-flow-requires-bind": context => ({
CallExpression: function(node) {
const ancestors = context.getAncestors();
const parent = ancestors.length > 0 && ancestors[ancestors.length - 1];
if (node.callee && node.callee.name === "flow") {
if (node.arguments.length === 1) {
const callee = node.arguments[0].callee;
if (!(callee && callee.property && callee.property.name === "bind")) {
context.report(node, "Calls to flow must be used with .bind");
}
}
}
}
})
};
您可以使用 this 教程将上述代码集成到您的存储库中。