When you have a type with a read-only property, you cannot convert any type that contains that property to the$Shape of that type.
Example: Try Flow
// @flow
type Foo = {
+bar: "baz";
};
const f: Foo = { bar: "baz" };
const g: $Shape<Foo> = { bar: "baz" };
In this example, the declaration of f typechecks, but the declaration of g fails with the confusing error message, "Cannot assign object literal to g because property bar is not writable in property bar."
Also having this issue. My use case is that I'd like to ensure that the props I'm returning from a mapStateToProps function are not wasted on the component:
import React, { PureComponent } from 'react';
type Props = {|
+foo: boolean,
|};
class MyComponent extends PureComponent<Props> {
static defaultProps = {
foo: false,
};
render() {
return (
<div>{this.props.foo ? 'foo' : 'nofoo'}</div>
);
}
}
const mapStateToProps = (): $Shape<Props> => ({
foo: true,
bar: true,
});
Errors:
19: const mapStateToProps = (): $Shape<Props> => ({
^ Cannot return object literal because property `bar` is missing in object literal [1] but exists in `Props` [2].
References:
19: const mapStateToProps = (): $Shape<Props> => ({
^ [1]
19: const mapStateToProps = (): $Shape<Props> => ({
^ [2]
19: const mapStateToProps = (): $Shape<Props> => ({
^ Cannot return object literal because property `foo` is not writable in property `foo`.
I was only expecting the first error.
The type spread operator can help you here. For @CGamesPlay's scenario
// @flow
type Foo = {
+bar: "baz";
};
const f: Foo = { bar: "baz" };
const g: $Shape<{...Foo}> = { bar: "baz" };
and in @zeorin's:
import React, { PureComponent } from 'react';
type Props = {|
+foo: boolean,
|};
class MyComponent extends PureComponent<Props> {
static defaultProps = {
foo: false,
};
render() {
return (
<div>{this.props.foo ? 'foo' : 'nofoo'}</div>
);
}
}
const mapStateToProps = (): $Shape<{...Props}> => ({
foo: true,
bar: true,
});
@phpnode That's great! I knew that the type spread operator is a way to turn an $Exact type into a regular inexact one, but didn't know that it would also make the props invariant.
Is that to say that $Shape doesn't have a bug and it's working as intended, or is it still a legit bug, and using the type spread operator is merely a workaround instead of The Wayâ„¢?
Would someone from the FB team would be able to verify if this is a bug or flow working as expected?
Using the type spread operator is not really a solution, it just destroys "readonlyness" and after that $Shape works ok.
type Props = {|
+foo: boolean,
|};
const value: $Shape<{...Props}> = { foo: true };
value.foo = false; // can write now without any error
Looks like this is fixed in 0.83.0.
Yup. Just came across this again, bumped to 0.83.0, error went away. This should be closed.
Thanks
Most helpful comment
@phpnode That's great! I knew that the type spread operator is a way to turn an
$Exacttype into a regular inexact one, but didn't know that it would also make the props invariant.Is that to say that
$Shapedoesn't have a bug and it's working as intended, or is it still a legit bug, and using the type spread operator is merely a workaround instead of The Wayâ„¢?