根据流程的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?
任何想法为什么?
答案 0 :(得分:1)
在较高级别,您可以重复使用objectB
实例,只需稍微修改ObjectA类型,也可以创建新对象。让我们深入了解您的选择:
您尝试做的是将ObjectB
投射到ObjectA
。 Flow抱怨的原因是foo
中ObjectA
的类型默认为invariant。 foo
的{{1}}属性是ObjectB
foo
属性的子类型。要让Flow了解这一点,我们只需要将ObjectA
属性标记为covariant:
(Try)
foo
将该物业标记为"协变"基本上说你保证只阅读那个属性,你不会写信给它。请注意,如果删除了objectA的// @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
属性,它将从objectB中删除baz
。通过将其标记为协变,如果您写入它,Flow将抛出错误:
(Try)
baz
此模式也适用于深层嵌套对象:
(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
有关此类型的更多详细信息,请参阅depth subtyping上的Flow文档。
// @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
Flow具有一个完整的类型$ReadOnly<T>
,可以将对象的所有属性标记为协变,因此您可能希望使用它:
(Try)
$ReadOnly<T>
或者您可以创建ObjectA的ReadOnly实例并单独保留ObjectA定义:
(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
或者,您可以使用跨页创建对象的新副本,并避免所有这些输入:
(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
但是这只能在一个深度上工作,它会创建一个额外的对象。通常,当我需要以只读方式使用对象时,我跳过此选项并最终使用// @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
。
答案 1 :(得分:0)
据我所知,一种可能的方法是展开对象。没有这个流程就无法读取属性。
SELECT * FROM `def_questions` where `question` LIKE '%What is your Name%'