-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
[WIP] Stronger types for React DOM #6727
Conversation
This is a first pass to start surfacing the architectural and practical issues involved in typing React DOM more precisely. In this commit: - No event props yet! - React global attributes like dangerouslySetInnerHTML - Shared HTML/SVG attributes - HTML global attributes - A handful of SVG global attributes - Lots of things marked TODO - Some design choices described in comments "Booleanish string" as a term is lifted from the React DOM source.
This is based on facebook/react#12507 which is seemingly missing a couple of fields from the official spec. Consequently this will need an update once React supports all fields.
facebook/react#13374 has been merged so the next React DOM release will have these fields.
This also refactors the main set of JSX intrinsics declarations to support typing Event.currentTarget with each element's instance type.
UPDATE: This is now described as a design choice in the main comment: #6727 (comment) In light of the issue outlined in facebook/react#13400, I'm currently thinking of removing
As with typing numeric properties as |
This is a design choice documented in facebook#6727 (comment)
Oh, nice. Some comments:
|
Yes in principle, I'm just trying to get to a point where I can see the overall "shape" of this work & see what the shippable milestones are along the way. Happy to get your thoughts on that. Also I didn't know what to expect in terms of a timeline for review/release etc (I'm glad to have your comments this early!), and as you see I'm still discovering some issues as I dive into specs and React's implementation thereof. Things like modelling |
This is still in progress, just had to take a break and focus on other things recently. There is an angle here that I think ties into the React team's longer-term plans for React DOM (facebook/react#13525). If ultimately we can model both today's React DOM and the future "React Fire" (which will include breaking API changes, e.g. potentially |
@motiz88 are you still working on this PR? |
@jbrown215 would there be parts in this that could be used from this pull request?? This is needed for improved Flowgen React support. |
I need as much as possible 😅This is the beef: joarwilk/flowgen#76 (comment) I'll try to pick up the parts that are needed the most. |
Yeah, actually part that is needed is not implemented here Also |
This is a design choice documented in facebook#6727 (comment)
This is a design choice documented in facebook#6727 (comment)
This is a design choice documented in facebook#6727 (comment)
Is there any chance to get this revived? |
Subsumed by #7569 |
Provides stronger prop type definitions for React DOM's JSX intrinsics.
This will be an ongoing project for a little while as the scope is ambitious. I'm opening this WIP PR for early feedback on the overall direction as well as for help from fellow interested developers. Pull requests to this branch welcome!
Will eventually close #3773 and close #5865.
Includes #6728 (
SyntheticPointerEvent
definition).Implementation checklist
autoCapitalize
(missed this in the initial pass)style
prop (a whole other can of worms 😅)children
anddangerouslySetInnerHTML
on void element tagsEvent.currentTarget
)Useful references
DOMProperty.js
inreact-dom
react-dom
event system implementation and docsDesign choices / constraints
(I am open to discussing all of these!)
Leave unknown props typed as
any
There is no way we can enumerate all acceptable/standard props of DOM intrinsics. If we ever got a Flow feature allowing regexes for keys, we could express open-ended namespaces like
data-*
attributes, custom attributes etc more precisely, and then maybe revisit this - with the goal of detecting more classes of errors, such as typos in prop names, or usage of attributes on elements that don't support them.For now the typing philosophy here is: be reasonably strict with the types of known attributes, but lenient otherwise. This means we can add some value with these types, but not quite match the DX of using composite components... yet.
any
ormixed
? The latter would seem to be more useful in scenarios other than passing attributes into elements (say, defining a custom component type that takesReact.ElementProps<button>
)Type numeric attributes as
number
React will not warn if you pass a string (be it
"1"
or"foo"
) into what's meant to be a numeric attribute, e.g.tabIndex
. However, I'm leaning towards the strictertabIndex?: number
in such cases. It's a judgement call, though, and an argument can be made fornumber | string
. I've created theReactDOM$Number
type alias as a reminder to come back to this after some discussion.Impose some case-sensitivity on enumerated attributes
In an ideal world we'd have a Flow builtin, perhaps called
$CaseInsensitive
, that makes the following possible:(EDIT: See separate issue about
$CaseInsensitive
- #6743)With such a hypothetical builtin (and I'm not the right person to build it - as I'm not fluent in OCaml by any stretch), we could model enumerated attributes correctly, as case-insensitive enums.
Here, rather than reverting to
string
for such attributes (or manually adding all letter case permutations of values), I've arbitrarily chosen to support what I think are common/natural-enough spellings.true
,false
) - support only the all-lowercase version.ltr
,rtl
) - support all-lowercase alongside all-uppercase (LTR
,RTL
).contentEditable
) - support camel-case alongside all-lowercase (contenteditable
).family-name
,street-address
) - only support the lowercase version.I am totally hoping that a Flow internals expert can come along and just give us
$CaseInsensitive
😄 In the meantime I've introduced the$TODO$CaseInsensitive
type as a placeholder.Forbid the value
""
in all kinds of boolean/enumerated propsThere are a few classes of DOM attributes that are "boolean", "booleanish" (a term from the React source) or "enumerated"; in HTML, these generally admit
""
as a valid value meaning "true". However, for some props, React DOM processes""
as a falsy JS value, omitting the attribute. This inconsistency, along with the fact that there is always a less-ambiguous way to specify "true" (foobar={true}
orfoobar="foobar"
) or an equivalent, is why I chose to model these props with union types that do not include""
- reducing the chance of users stumbling across surprising behaviour.