简体   繁体   English

如何通过控制流缩小变量类型?

[英]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处理可变值t1T1属性没有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};
}

You may want to check every time if a has a property b :您可能希望每次都检查a是否具有属性b

let c = ('b' in t1.a)? t1.a.b : undefined;

Here is a link to learn more about in operator下面是更多地了解一个链接in运营商

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何提取条件是否起作用而不破坏 TypeScript 中的缩小类型 - How to extract if condition to function and not break narrowed types in TypeScript Typescript解决方法返回缩小的类型 - Typescript workaround to return narrowed types 元组联合类型的控制流分析 - Control flow analysis for Tuple Union Types Typescript中部分类型的并集不能缩小类型 - Union of partial types in Typescript can't be type-narrowed 带有 extends 子句的泛型类型并不总是像应有的那样缩小范围 - Generic types with an extends clause doesn't always get narrowed down like they should 使用strictNullChecks进行TypeScript的控制流分析不会缩小联合类型 - TypeScript's control flow analysis with strictNullChecks does not narrow down union types 如何像流一样在 Typescript 中定义条件字符串类型? - How to define conditional string types in Typescript like flow? 如何通过 Typescript 为 Flow 导入 React-Native 类型? - How to import React-Native types via Typescript for Flow? 当传递给闭包时,类型缩小的 `let` 变量恢复为其原始类型 - Type-narrowed `let` variable reverts to its original type when passed to a closure 如何控制服务调用的流程,使用 rxjs 和 Angular 9? - How to control the flow of service calls, using rxjs with Angular 9?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM