-
Notifications
You must be signed in to change notification settings - Fork 349
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
POC of giving a type-error for non keyed elements when are under React.array #812
Conversation
type component('props) = componentLike('props, element); | ||
type element('a); /* 'a captures any type information to differenciate with others 'a's */ | ||
|
||
type keyed; /* Flag to mark element('a) to be keyed */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a note, I think this won't work correctly after ocaml/ocaml#8900
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally, we can workaround it by adding "private" fields:
type keyed = private Tag_keyed
type non_keyed = private Tag_non_keyed
I need to look at this thoroughly, but one thing that obviously becomes harder is annotating since there's the new phantom type variable for |
cc @mlms13 @maxkorp @andywhite37 @endlo would love your input on this if you can. |
I started testing the approach in #813 (which is in the end very similar to this 😄 ) and noticed a case in reshowcase that breaks. The code breaks here with this error:
The code does something like this: Array.map(((entityName, entity)) => {
let searchMatchingTerms =
HighlightTerms.getMatchingTerms(~searchString, ~entityName);
let isEntityNameMatchSearch =
searchString == "" || searchMatchingTerms->Belt.Array.size > 0;
switch (entity) {
| Demo(_) =>
if (isEntityNameMatchSearch || parentCategoryMatchedSearch) {
<Link
key=entityName
...
/>;
} else {
React.null;
}
... I think the error makes sense. I am not sure what the fix should be. React supports |
I believe this is a bug in our code, right? An array of elements where some of them are null seems a bad JSX construction. I have coded myself worst atrocities and later filtering out React.nulls. |
True. Splitting the processing in 2 steps:
solves the issue. See ahrefs/reshowcase@68718ce for the fix (it includes another fix for unneeded |
Another interesting case I found is [@react.component]
let make = (~children) =>
<ol>
{children->React.Children.mapWithIndex((element, index) =>
<li key={string_of_int(index)}> element </li>
)}
</ol>; I fixed it in 29fc9be. I spent some time applying the typed keys to ahrefs monorepo, I am far from finished but I found already 5 bugs of elements that were missing keys. There were also 10+ places where keys were added unnecessarily. I think the largest pain points are:
In general, my impression is that this improvement could be very useful, and once folks get used to how the types work, the advantages would overcome the downsides. @davesnx @johnhaley81 thanks for proposing it! ❤️ |
Ah, another thing I forgot is that https://react.dev/reference/react/Children |
That's very suspicious, people rarely add keys without a good reason. |
Introduced an idea where there's a difference between elements/components with keys. Useful for the type-checker to raise an issue where keys aren't passed, but React.array needs them.
The implementation of the types goes as follow:
So all usages of
element_without_key
andelement_with_key
can be explicit on the bindings.@johnhaley81
Pros of this PR
Example of the type error:
Cons