gpt4 book ai didi

javascript - 深度子类型的流错误

转载 作者:行者123 更新时间:2023-11-29 15:15:00 24 4
gpt4 key购买 nike

根据 Subtypes of objects 文档的流程,这是有效的

// @flow
type ObjectA = { foo: string };
type ObjectB = { foo: string, bar: number };

let objectB: ObjectB = { foo: 'test', bar: 42 };
let objectA: ObjectA = objectB; // Works!

但是更深层次的实现并没有

// @flow
type ObjectA = { foo: { bar: string } };
type ObjectB = { foo: { bar: string, baz: string } };

let objectB: ObjectB = { foo: { bar: '123', baz: '456' } };
let objectA: ObjectA = objectB; // Error! Why?

有什么想法吗?

最佳答案

在高层次上,您可以通过对 ObjectA 类型进行轻微修改来重用 objectB 实例,也可以创建一个新对象。让我们深入了解您的选择:

将对象属性标记为协变

您要做的是将 ObjectB 转换为 ObjectA 。 Flow 提示的原因是 fooObjectA 的类型默认是 invariantfooObjectB 属性是 fooObjectA 属性的子类型。为了让 Flow 理解这一点,我们只需要将 foo 属性标记为 covariant :

( Try )

// @flow
type ObjectA = { +foo: { bar: string } };
type ObjectB = { foo: { bar: string, baz: string } };

let objectB: ObjectB = { foo: { bar: '123', baz: '456' } };
let objectA: ObjectA = objectB; // Woohoo, no error

将属性标记为“协变”基本上表示您 promise 只读取该属性,不会写入它。看,如果您删除了 objectA 的 baz 属性,它会从 objectB 中删除 baz。通过将其标记为协变,Flow 将在您写入时抛出错误:

( Try )

// @flow
type ObjectA = { +foo: { bar: string } };
type ObjectB = { foo: { bar: string, baz: string } };

let objectB: ObjectB = { foo: { bar: '123', baz: '456' } };
let objectA: ObjectA = objectB;

objectA.foo = {bar: 'oh-oh, deleted baz in objectB'}; //Error

此模式也适用于嵌套更深的对象:

( Try )

// @flow
type ObjectA = { +foo: { +bar: { baz: string } } };
type ObjectB = { foo: { bar: { bax: string, baz: string } } };

let objectB: ObjectB = { foo: { bar: { bax: '123', baz: '456' } } };
let objectA: ObjectA = objectB; // Woohoo, no error

有关此类型的更多详细信息,请参阅 depth subtyping 上的 Flow 文档。

使用 $ReadOnly<T>

Flow 有一个实用类型 $ReadOnly<T> ,用于将对象的所有属性标记为协变的,因此您可能想改用它:

( Try )

// @flow
type ObjectA = $ReadOnly<{ foo: { bar: string } }>;
type ObjectB = { foo: { bar: string, baz: string } };

let objectB: ObjectB = { foo: { bar: '123', baz: '456' } };
let objectA: ObjectA = objectB; // Woohoo, no error

或者您可以创建 ObjectA 的 ReadOnly 实例并单独保留 ObjectA 定义:

( Try )

// @flow
type ObjectA = { foo: { bar: string } };
type ObjectB = { foo: { bar: string, baz: string } };

let objectB: ObjectB = { foo: { bar: '123', baz: '456' } };
let objectA: $ReadOnly<ObjectA> = objectB; // Woohoo, no error

创建一个新对象

或者,您可以使用展开创建对象的新副本并避免所有这些输入:

( Try )

// @flow
type ObjectA = { foo: { bar: string } };
type ObjectB = { foo: { bar: string, baz: string } };

let objectB: ObjectB = { foo: { bar: '123', baz: '456' } };
let objectA: ObjectA = {...objectB} // Create a new object

但这只会在一层深度起作用,并且会创建一个额外的对象。通常,当我需要以只读方式使用对象时,我会跳过此选项并最终使用 $ReadOnly<T>

关于javascript - 深度子类型的流错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50145934/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com