如何在使用 Flow 时将 props 传播到使用精确 props 的 React 组件?

Pau*_*ong 6 javascript reactjs flowtype

考虑以下使用流道具的示例。

import * as React from 'react';

type FooProps = {| 
  foo: number,
  bar?: string 
|};

class Foo extends React.Component<FooProps> {}
Run Code Online (Sandbox Code Playgroud)

我们有 React 组件类Foo,它接受一个确切的道具对象。我们希望强制执行准确性,以便用户不会无意中在他们的道具上打错字(例如,baz当他们打算使用 时bar)。

这绝对可以正常工作,并且会按预期发生错误。

但是,如果我们想从其他地方将 props 传播到这个组件怎么办?例如:

const f = (props: FooProps) => <Foo {...props} />;
Run Code Online (Sandbox Code Playgroud)

Flow 会给我们一个关于正确性的错误props

10: const f = (props: FooProps) => <Foo {...props} />;
                                    ^ Cannot create `Foo` element because inexact props [1] is incompatible with exact `FooProps` [2].
References:
10: const f = (props: FooProps) => <Foo {...props} />;
                                   ^ [1]
8: class Foo extends React.Component<FooProps> {}
                                     ^ [2]
Run Code Online (Sandbox Code Playgroud)

抛开论点,“当你要求精确性时,你不应该像那样将 props 传播到组件上”,如何实现传播?

我确实找到了一种方法来做到这一点,但它使用了一种未记录的实用程序类型$Shape<T>code)。目前尚不清楚这是否有任何后果或副作用,但它似乎可以正常工作:

class Foo extends React.Component<$Shape<FooProps>> {}
Run Code Online (Sandbox Code Playgroud)

这是一个链接,用于尝试使用$Shape<T>我预计会出错(而不是)的项目:

Dav*_*han 7

如果这不是来自官方来源,我们深表歉意。

解决方案:any在传播之前键入 cast props 。

它满足您在函数内传播的要求。该函数在类型转换之前确保准确性。

注意:$Shape<FooProps>在演员表上不起作用,它仍然认为它是准确的。尽管在您的示例中出现了,但分配props给 a const spreadable: $Shape<FooProps> = props It 似乎$Shape并没有消除准确性。以一种或另一种方式,您必须剥离准确性,并在内部执行该功能似乎是合理的。

Flow 文档讨论了any合法的类型转换,尽管可能不安全并且不推荐(因为您失去了类型安全)。我认为在上下文中它是合理的。

import * as React from 'react';

type FooProps = {| 
  foo: number,
  bar?: string 
|};

class Foo extends React.Component<FooProps> {}

const f = (props: FooProps) => <Foo {...(props: any)} />;

f({foo: 1})                     // PASS: with foo, without bar
f({foo: 1, bar: ''})            // PASS: with foo and bar
{ <Foo foo={1} /> }             // PASS: with foo, without bar
{ <Foo foo={1} bar="" /> }      // PASS: with foo and bar

f({})                           // FAIL: missing foo
f({foo: ''})                    // FAIL: wrong type of foo
f({foo: 1, bar: 1})             // FAIL: with foo, wrong type of bar
f({foo: 1, x: 1})               // FAIL: unexpected x
{ <Foo /> }                     // FAIL: missing foo
{ <Foo foo="" /> }              // FAIL: wrong type of foo
{ <Foo foo={1} bar={1} /> }     // FAIL: with foo, wrong type of bar
{ <Foo foo={1} x={1} /> }       // FAIL: unexpected x
Run Code Online (Sandbox Code Playgroud)

在这里试试