简体   繁体   English

对不可为空的流类型细化不起作用

[英]Flow type refinement to non-nullable doesn't work

Somewhere in my Flow annotated JavaScript code I have an object obj defined with nullable field field .在我的 Flow 注释的 JavaScript 代码中的某个地方,我有一个对象obj定义为可空字段field

let obj: { field: ?number } = { field: 1 };

I have a function func that accepts argument arg which has the same structure as obj but field should be non-nullable at this time.我有一个函数func接受参数arg ,它与obj具有相同的结构,但此时field应该是不可为空的

function func(arg: {field: number}){
    // do something
}

I'm calling the func with obj after checking that the obj.field is not null or undefined , hoping that Flow will do it's type refining magic and understand that obj.field is always number and it's type is OK to pass to the func .在检查obj.field不是nullundefined之后,我正在用obj调用func ,希望 Flow 会做它的类型精炼魔法并理解obj.field总是number并且它的类型可以传递给func

if(obj.field !== null && obj.field !== undefined){
    func(obj);
}

Surprisingly getting an error, Flow doesn't like it:出人意料地得到一个错误,Flow 不喜欢它:

14:   func(obj);
           ^ Cannot call `func` with `obj` bound to `arg` because null or undefined [1] is incompatible with number [2] in property `field`.
References:
4:   field: ?number            ^ [1]
9: function func(arg: {field: number}){
                              ^ [2]

Run online in the Try Flow 在试用流程中在线运行

Two questions:两个问题:

  1. Why doesn't it work?为什么不起作用?
  2. What is best practice to make it work?让它发挥作用的最佳实践是什么?

The code snippets above are simplified version of the code to demonstrate the problem.上面的代码片段是用于演示问题的代码的简化版本。 Actual obj is more complex.实际的obj更复杂。

First-off, Flow's refinement applies to individual fields here, but generally you aren't refining the whole object's type, so you can't refine an object's type based on refinement of a single field (as far as I'm aware).首先,Flow 的细化适用于此处的单个字段,但通常您不会细化整个对象的类型,因此您不能基于对单个字段的细化来细化对象的类型(据我所知)。 Even if you could, this example would still not be typesafe.即使你可以,这个例子仍然不是类型安全的。 Here's something that illustrates the problem with allowing this:以下内容说明了允许这样做的问题:

let obj: { field: ?number } = { field: 1 };

if(obj.field !== null && obj.field !== undefined){
    func(obj);

    obj.field = null;
}

function func(arg: {field: number}){
    setTimeout(() => {
      var value: number = arg.field;
    }, 10);
}

Given purely the restrictions you're looking for, this would typecheck, but the value inside the func timeout callback would actually be null .纯粹考虑到您正在寻找的限制,这将进行类型检查,但func timeout 回调中的value实际上是null

The only way your given code could be safe with typechecking is if the arg.field value were marked contravariant (note the - in the property name for func now, eg您给定的代码在类型检查时安全的唯一方法是arg.field值是否被标记为逆变(注意-现在在func的属性名称中,例如

let obj: { field: ?number } = { field: 1 };

if(obj.field !== null && obj.field !== undefined){
    func(obj);
}

function func(arg: {-field: number}){
  arg.field = 43;
}

( On Flow Try ) 在流尝试

This effectively would make arg.field write-only, which is fine because writing a number to field would always be safe, but reading one is not safe in the long term.这将有效地使arg.field只写,这很好,因为数字写入field总是安全的,但从长远来看,读取一个数字并不安全。

What is best practice to make it work?让它发挥作用的最佳实践是什么?

It depends on what your real code does, to some extent.在某种程度上,这取决于您的真实代码的作用。 In this specific example I'd say pass the number directly as the argument, but assuming it needs to be an object, you could consider creating a new object with just the properties func needs.在这个特定示例中,我会说直接将数字作为参数传递,但假设它需要是一个对象,您可以考虑创建一个仅具有func所需属性的新对象。

暂无
暂无

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

相关问题 Flow为什么不理解可为空的属性与不可为空的对象属性兼容? - Why doesn't Flow understand that nullable properties are compatible with non-nullable object properties? 流:优化不适用于自定义类型 - Flow: refinement not work on custom type 如果通过另一个变量检查​​是否为null / undefined,流程类型优化将不起作用 - Flow type refinement doesn't work if check null/undefined through another vairable 将 Flow/TypeScript JavaScript object 值类型转换为不可为空 - Cast Flow/TypeScript JavaScript object value types to non-nullable GraphQL 的不可为空错误没有提供太多细节,这可能让我进行调查 - Non-nullable error with GraphQL doesn't give much detail which might allow me to investigate 事件中的流类型细化 - Flow type refinement in events GraphQL:不可为空的数组/列表 - GraphQL: Non-nullable array/list 模式弹出错误:“参数字典包含非空类型参数'id'的空条目 - Modal popup error: "The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 参数字典包含非空类型“ System.Int32”的参数“ imageWidth”的空条目 - The parameters dictionary contains a null entry for parameter 'imageWidth' of non-nullable type 'System.Int32' 参数字典包含非空类型'System.Int32'的参数'talepID'的空条目 - The parameters dictionary contains a null entry for parameter 'talepID' of non-nullable type 'System.Int32'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM