为什么 `{ a: string }` 不能流入 `{ a?: string }`

Why can't `{ a: string }` flow into `{ a?: string }`

给定对象类型 AB 除了 A 的属性是可选的之外它们是相同的......为什么不能 B 就地使用A 在哪里被接受?

type A = { a?: string };
type B = { a: string };

const x: B = { a:'…' };

// …string is incompatible with undefined in property `a`
(x: A)

Flow try link here

我认为 Flow 试图警告如果 x 被输入为 A 那么它可能会被修改以使其仍然满足 A 的类型定义但是不满足 B 的类型定义。例如,您可以删除 a 属性 if x: A,这将违反 B.

我通过创建 A 的新 "read only" 版本并将 x 转换为它来测试它。

type Required = { a: string};
type Optional = { a?: string };
type ReadOnlyOptional = $ReadOnly<Optional>;

const x: Required = { a: '' };
(x: Optional); // error
(x: ReadOnlyOptional); // no error!

Try Flow

为了能够执行类型转换,要转换的类型必须包含在当前类型的类型定义中。

在这种情况下

type A = { a?: string };
type B = { a: string };

无法转换这些类型,无论是 A > B 还是 B > A,因为它的类型定义不匹配。

如果您定义了下一个类型:

type A = { a?: string };
type B = { a?: string, b: number };

你可以从类型 B 转换为类型 A

const x: B = { a: '...', b: 1 };
(x: A)

const x: B = { b: 1 };
(x: A)

这些都是有效的,因为类型 A 包含在类型 B 中。

但是您不能从类型 A 转换为类型 B,因为类型 A 的定义不包含在类型 B 中。

const x: A = { a: '...' };
(x: B)

此转换失败。