提问人:cglacet 提问时间:9/18/2023 更新时间:9/18/2023 访问量:60
打字稿是否总是假设不允许副作用?
Does typescript always assumes side effects are not allowed?
问:
我有以下玩具示例,其中打字稿警告我错误:
type obj = {
ok: "ok" | "error",
}
function main(a: obj){
a.ok = "ok";
reloadFromDatabase(a);
if (a.ok == "error"){ // TS error
console.log("Error");
}
}
// Any function that has side effects on object a.
// For example, typeorm's `a.reload()`
function reloadFromDatabase(a: obj){
a.ok = "error";
}
错误是:
This comparison appears to be unintentional because the types '"ok"' and '"error"' have no overlap.(2367)
如果您假设不允许突变对象的副作用,这是有道理的,但 的类型是 所以它应该允许 的两个值 () 。a
obj
"ok" | "error"
obj.isOk
在这个特定的代码示例中,我掌握了具有副作用的函数,因为它很好,因为我可以返回突变的对象:
function main(a: obj){
a.ok = "ok";
a = reloadFromDatabase(a);
if (a.ok == "error"){ // This time its fine
console.log("Error");
}
}
function reloadFromDatabase(a: obj){
a.ok = "error";
return a;
}
但是在我的用例中,我无法访问它,它什么也没返回(它只是改变了对象)。reloadFromDatabase
这是打字稿选项吗?这似乎是一个合法的错误吗?我是否错过了允许突变会完全破坏打字稿逻辑(提供较少/没有类型安全性)的情况?
答:
2赞
Matthieu Riegler
9/18/2023
#1
这是在控制流分析中做出的权衡的一部分:
你可以看看这个著名的问题:https://github.com/microsoft/TypeScript/issues/9998
可以总结为以下问题:
主要问题是:当一个函数被调用时,我们应该做什么 假设它的副作用是?
现在,TS假设没有副作用。
解决方法是使用类型断言:
if (a.ok as obj['ok'] == "error") { // ok asserted as 'ok'|'error'
console.log("Error");
}
评论
1赞
Jared Smith
9/18/2023
不是 DV,但这个答案绕过了仅链接的界限,尤其是在您添加变通方法代码块之前。也许在答案的文本中添加一些链接的 github 线程的嘶嘶声?
1赞
Matthieu Riegler
9/18/2023
你是对的,答案应该更好一点
0赞
cglacet
9/19/2023
总结这个巨大的线索对我来说确实很重要。解决方法确实解决了我的问题。
0赞
cglacet
9/19/2023
也许有一个例子会很有趣,说明如果不做出这个假设会有什么突破(感受一下这里所做的妥协)?
评论