-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Writeonly<S> as a solution for the problem with React's setState() and strictNullChecks #27521
Comments
You have checked the third point of the checklist, but how would this work without emitting different JS? Your property In order for this to work as you imagine it you would need to actually remove the property from the object at run-time again, so instead of just type information you need additional JavaScript that would change
to
|
Sorry, that line of code was only an illustration of why I have edited the post above and converted the line into a comment. |
I would like to add that today the code above can be achieved by lying about the type with handleClick = () => {
let s = {} as S;
console.log(s.foo); // Problem: s.foo has the type number in TypeScript, but it is undefined.
// That's why reading from Writeonly<S> should not be allowed
s.foo = 1;
this.setState(s);
}; But this is much less safe, because you could read PS: This additional safety might not seem very important, but keep in mind that this minimal code sample does not reflect real world applications in any way. In real applications the state objects can be quite a lot larger and the state updating logic can involve a lot of if-conditionals, etc. |
I think most people would prefer just |
Yes, that's better for simple cases indeed. But it doesn't allow you to make an assignment based on a condition. Let's say you want to update if (condition) {
this.setState({ foo: 1, bar: 2 });
}
this.setState({ a: 1, b: 2 }); However, the problem with multiple So if you want to do it in a single let state = {} as S;
if (condition) {
state.foo = 1;
state.bar = 2;
}
state.a = 1;
state.b = 2;
this.setState(state); This is the only way to do it with a single And now imagine that you are doing this in a larger application with more complex state objects/logic. It would definitely be helpful to be able to communicate to other programmers on the team that this is a non-readable object. |
Duplicate #21759 ? |
@andy-ms this is usually a problem when writing The following example cannot compile at all with the current type definitions: this.setState((state, props) => {
if (props.foo) {
return { bar: state.bar + 1 }
}
return { baz: state.baz - 1 }
}) A workaround is to copy the value you want to preserve; adding |
@RyanCavanaugh Thanks for pointing me to the other issue. I haven't read the entire discussion yet, so I'm not sure if that would allow the creation of an empty object like this: let s: Writeonly<S> = {}; // S has many required keys I will read through that issue when I have some more time. @Kovensky Thanks, that is another great example of why something like this is needed! That situation is exactly why I created this feature request. |
This issue has been marked as a duplicate and has seen no activity in the last day. It has been closed for automatic house-keeping purposes. |
Search Terms
I found these similar issues:
#12793 (closed without a proper solution)
#13359 (quite a different use case/problem + no solution offered)
Suggestion
My suggestion would be a new special generic
Writeonly<S>
(the opposite ofReadonly<S>
).Like that you could write code like this:
Use Cases
Using React's setState() in conjunction with strictNullChecks, which still doesn't have a proper solution. Neither
Pick<S, T>
norPartial<S>
are very useful when strictNullChecks is enabled. Especially when you need to update properties in an if-branch.Checklist
My suggestion meets these guidelines:
The text was updated successfully, but these errors were encountered: