Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/434.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是否流动';“结构子类型”;“忘了吧”;特定子类型属性?_Javascript_Types_Flowtype_Static Typing_Structural Typing - Fatal编程技术网

Javascript 是否流动';“结构子类型”;“忘了吧”;特定子类型属性?

Javascript 是否流动';“结构子类型”;“忘了吧”;特定子类型属性?,javascript,types,flowtype,static-typing,structural-typing,Javascript,Types,Flowtype,Static Typing,Structural Typing,我目前正在学习结构打字。我怀疑这两种类型被认为是等同的,仅仅因为它们碰巧有一部分结构相同。这感觉很像静态duck类型,它完全忽略了类型的语义级别。因此,我仔细研究了flow对普通对象的结构类型,并遇到了以下行为: const o:{} = {foo: true}; o.foo; // type error {}是一种结构类型,是所有普通对象的超类型。因此,我可以用它注释o,因为{foo:true}是{}的结构子类型。但是,当我尝试访问现有的foo属性时,此操作不会进行类型检查。这很奇怪,因为A

我目前正在学习结构打字。我怀疑这两种类型被认为是等同的,仅仅因为它们碰巧有一部分结构相同。这感觉很像静态duck类型,它完全忽略了类型的语义级别。因此,我仔细研究了flow对普通对象的结构类型,并遇到了以下行为:

const o:{} = {foo: true};
o.foo; // type error
{}
是一种结构类型,是所有普通对象的超类型。因此,我可以用它注释
o
,因为
{foo:true}
{}
的结构子类型。但是,当我尝试访问现有的
foo
属性时,此操作不会进行类型检查。这很奇怪,因为AFAIK结构子类型通常可以包含特定属性,只要它还包含其超类型的所有必需属性


似乎flow的结构子类型算法偶尔会忘记特定于某个子类型的属性。这种行为是故意的还是我只是遇到了边缘情况?

您所描述的总体问题是从子类型转换为超类型的事实。通过执行强制转换,您明确地告诉编译器放弃关于给定对象的信息

例如,即使没有结构类型,如果您

class Animal {}

class Cat extends Animal {
  foo: bool = true;
}

const c: Animal = new Cat();

console.log(c.foo);
()

出于同样的原因,它无法进行打字检查。在您的示例中,您明确告诉编译器“考虑
o
使用类型
{}
”,就像在我的示例中我说的“考虑
c
使用类型
Animal
”。因此,编译器被明确告知忘记它正在使用
Cat
,因此它忘记对象具有
.foo
属性

似乎flow的结构子类型算法偶尔会忘记特定于某个子类型的属性。这种行为是故意的还是我只是遇到了边缘案例

所以要回答这个问题,它不会“偶尔”做,它会在你让它做的时候做。这种行为完全是故意的

这很奇怪,因为AFAIK结构子类型通常可以包含特定属性,只要它还包含其超类型的所有必需属性


对象确实包含该属性,这是100%正确的,但是通过将值强制转换为超类型,您已经明确删除了该信息。

您能澄清一下您的意思吗?通过声明类型
:{}
,您已经显式地删除了关于它的类型信息,就像您这样做了
Animal foo=new Cat()
foo
不知道它是
Cat
,它只知道它是
Animal
@loganfsmyth
{}
只是最普通的对象类型,没有任何结构。这当然是毫无用处的。问题是,我观察到的这个边缘案例的行为是否是一个更深层次问题的一部分,这是特定于子类型的。我想澄清的是,你认为边缘案例是什么,它会是什么问题?在JavaScript作为一种非类型化语言的情况下,绝对存在这样的情况:您拥有一个对象,却对它所拥有的属性一无所知。要获得
foo
,您可以使用
if(typeof o.foo==“boolean”){/*将属性作为boolean*/}
进行处理,这将非常有用。也许这将有助于澄清
{}
是“具有未知属性的对象”,这可能很有用,而
{|}
是“没有属性的对象”这是非常无用的。
o
是一个具有属性
foo
bar
的对象,但是由于您将其强制转换为超类型
o
,类型系统不再知道它具有属性
bar
。这和你在类似的事情中看到的失败类型是一样的。一旦您告诉类型系统它是一个
O
,它就知道了。是的,对象有其他属性,但是您已经明确告诉类型系统忘记它们在那里。Flow的结构类型允许您强制转换它们,但是如果您强制转换为超类型,则在类层次结构中也会遇到同样的问题。这肯定不是我最好的问题之一。无论如何,感谢您抽出时间回答!因此,真正的问题是,当没有任何显式注释但必须推断类型时,流的行为如何,因为对象是由更复杂的组合中的函数返回的。还有信息丢失吗?相关:我觉得我需要一个明确的例子,但据我所知,在类型推断中不应该丢失任何信息。