请考虑以下使用流量道具的示例。
import * as React from 'react';
type FooProps = {|
foo: number,
bar?: string
|};
class Foo extends React.Component<FooProps> {}
我们有React组件类Foo
,它接受一个确切的props对象。我们希望强制执行准确性,以便用户不会无意中对其道具进行拼写错误(例如baz
,当他们打算使用bar
时)。
这非常正常,错误会按预期发生。
但是,如果我们想从其他地方向这个组件传播道具呢?例如:
const f = (props: FooProps) => <Foo {...props} />;
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]
忽视这个论点,&#34;当你要求准确性时,你不应该将道具传播给那些组件,如何实现传播?
我确实找到了一种方法来执行此操作,但它使用了未记录的实用程序类型$Shape<T>
(code)。目前还不清楚这是否有任何后果或副作用,但它似乎正常工作:
class Foo extends React.Component<$Shape<FooProps>> {}
这里有一个link to try out what I've got using $Shape<T>
,其中包含我希望错误的项目(而不是):
答案 0 :(得分:2)
如果这不是来自官方来源,请道歉。
解决方案:在传播之前将投射道具键入any
。
它符合您在功能中传播的要求。该功能可确保在类型转换之前的准确性。
注意:演员表上的$Shape<FooProps>
不起作用,它仍然认为是准确的。也没有将props
分配给const spreadable: $Shape<FooProps> = props
似乎$Shape
不会删除准确性,尽管在您的示例中出现了。无论如何,你必须剥离正确性,并在内部执行该功能似乎是合理的。
The Flow docs discuss type casting via any
as legitimate虽然潜在的不安全而且不推荐(因为你放松了类型安全)。我认为在上下文中它是合理的。
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
答案 1 :(得分:1)
看起来这是一个非常常见的问题:Exact fails when doing es6 object spread
该线程中建议的一个选项是使用:
type Exact<T> = T & $Shape<T>
然后不要与{||}
完全一致地编写您的类型:
type FooProps = {
foo: number,
bar?: string
}
class Foo extends React.Component<Exact<FooProps>> {}
这将允许您使用spread运算符并仍然可以自动完成属性。