[英]How are variable types narrowed with control flow?
After having read this question , I am trying to find out, how variables can be narrowed down with the control flow.阅读完这个问题后,我试图找出如何通过控制流缩小变量的范围。 An example:
一个例子:
type T1 = {
a?: {
b: string
}
}
const t1: T1 = {}
t1.a.b // error, possibly undefined
t1.a = { b: "foo" }
t1.a.b // works now, TS recognizes, that property a now exists
The concrete case, where I am struggling currently:具体案例,我目前正在苦苦挣扎:
const t1: T1 = {}
t1.a = { b: "foo" }
function foo(t: T1) {
t.a = undefined
}
foo(t1) // function foo mutates prop "a" inside to be undefined again
// t1.a = undefined ; this would correctly emit error
console.log(t1.a.b) // ... "a" is still regarded as defined here and TS compiles successfully :/
// This will be a runtime error.
I would expect TS to recognize, that foo
processes the mutable value t1
(properties in T1
do not have readonly
flag).我希望 TS 能够识别出
foo
处理可变值t1
( T1
属性没有readonly
标志)。 foo
potentially could have changed the value (in this case it does indeed), so the compiler should reset all previous narrowing types of t1
and report a
in console.log(t1.ab)
as possibly undefined
again. foo
可能已经改变了值(在这种情况下它确实改变了),所以编译器应该重置所有以前的t1
缩小类型,并在console.log(t1.ab)
报告a
可能再次undefined
。
My question now is: How sophisticated is this control flow mechanism and what rules does it obey to with regard to above example?我现在的问题是:这个控制流机制有多复杂,它遵循什么规则关于上面的例子? Here is the link to the code .
这是代码的链接。 Thank you!
谢谢!
Function foo
is typical side-effectfull function, it gets an argument, change it, and returns void
.函数
foo
是典型的副作用函数,它获取一个参数,更改它,并返回void
。 TS does follow code by top->down flow, so it checks if foo
gets the proper argument, but does not control what it does with it and how it influence scope above. TS 确实按照自上而下的流程遵循代码,因此它检查
foo
获得了正确的参数,但不控制它用它做什么以及它如何影响上面的作用域。 The only way to inform scope above what we did is to return the value.将我们所做的事情告知范围的唯一方法是返回值。 Currently the only information for outer scope about
foo
is that it wants T1
as an argument, and its not giving anything back.目前关于
foo
外部作用域的唯一信息是它希望T1
作为参数,并且它不回馈任何东西。
Want to mention that, such implementation of implicit argument change is an anti-pattern also, as foo
is very unsafe function to use, which does not inform on the type level what it does(it has no return).想提一下,这种隐式参数更改的实现也是一种反模式,因为
foo
是使用起来非常不安全的函数,它不会在类型级别上告知它的作用(它没有返回)。 We can inform top scope about the change by returning the changed value.我们可以通过返回更改的值来通知 top scope 更改。 Consider below:
考虑以下:
let t1: T1 = {} // change to let
t1.a = { b: "foo" }
function foo(t: T1) {
t.a = undefined
return t; // return what was changed
}
t1 = foo(t1) // function return mutated value
console.log(t1.a.b) // error as a is undefined
In that way TS is able to infer return of foo
and its impact on the outer scope.通过这种方式,TS 能够推断出
foo
返回及其对外部作用域的影响。
And even better is to make foo
a pure function (yes this is only opinion):更好的是让
foo
成为一个纯函数(是的,这只是意见):
function foo(t: T1) {
return {...t, a: undefined};
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.