如何使用 `$Diff` 验证可选字段?

How to validate optional fields with `$Diff`?

我希望我的类型验证传递给 React 组件的 "default props",但是 $Diff(为此而设计)没有这样做。我怎样才能得到这种行为?

/* @flow */

type Props = { name: string, age: number };
type DefaultProps = { age: number };
type RequiredProps = $Diff<Props, DefaultProps>;

const a1: RequiredProps = { name: 'foo' };
const a2: RequiredProps = { name: 'foo', age: 1 };
const a3: RequiredProps = { name: 'foo', age: '1' }; // why no error?

$Diff<A, B> returns 一种默认情况下将接受附加属性的对象类型。这意味着 AB 上的任何属性都可以在任何类型的 $Diff<A, B> 类型的对象上。在您的例子中,RequiredProps 等同于 { name: string }。因此,对象 { name: '', age: <whatever> }: RequiredProps 对于 <whatever>.

的任何值都是完全有效的

看来您真正想要的是一个对象类型,它需要 RequiredProps 的所有属性,并且需要来自 DefaultProps 匹配该类型定义。这可以通过类型来实现,

type RequiredAndDefaultProps = { ...$Exact<RequiredProps>, ...DefaultProps };

可以验证

type Props = { name: string, age: number };
type DefaultProps = { age: number };
type RequiredProps = $Diff<Props, DefaultProps>;
type RequiredAndDefaultProps = { ...$Exact<RequiredProps>, ...DefaultProps };

({ name: 'foo' }: RequiredAndDefaultProps);
({ name: 'foo', age: 42 }: RequiredAndDefaultProps);
({ name: 'foo', age: '42' }: RequiredAndDefaultProps); // Error: age should be number
({ age: 42 }: RequiredAndDefaultProps); // Error: missing name
({ name: 'foo', bar: 'bar' }: RequiredAndDefaultProps);

Try Flow.