-
Notifications
You must be signed in to change notification settings - Fork 30.5k
[@types/react] add VoidFunctionComponent type which does not accept "children" #46643
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
Conversation
@awmottaz Thank you for submitting this PR! I see this is your first time submitting to DefinitelyTyped 👋 — I'm the local bot who will help you through the process of getting things through. This is a live comment which I will keep updated. 1 package in this PRCode ReviewsBecause you edited one package and updated the tests (👏), I can help you merge this PR once someone else signs off on it. Status
All of the items on the list are green. To merge, you need to post a comment including the string "Ready to merge" to bring in your changes. Diagnostic Information: What the bot saw about this PR{
"type": "info",
"now": "-",
"pr_number": 46643,
"author": "awmottaz",
"owners": [
"johnnyreilly",
"bbenezech",
"pzavolinsky",
"digiguru",
"ericanderson",
"DovydasNavickas",
"theruther4d",
"guilhermehubner",
"ferdaber",
"jrakotoharisoa",
"pascaloliv",
"hotell",
"franklixuefei",
"Jessidhia",
"saranshkataria",
"lukyth",
"eps1lon",
"zieka",
"dancerphil",
"dimitropoulos",
"disjukr",
"vhfmag",
"hellatan"
],
"dangerLevel": "ScopedAndTested",
"headCommitAbbrOid": "9aa5631",
"headCommitOid": "9aa5631278d887b0f5594e76041b7cc316564d5e",
"mergeIsRequested": true,
"stalenessInDays": 0,
"lastPushDate": "2020-08-19T13:16:05.000Z",
"lastCommentDate": "2020-08-26T19:31:40.000Z",
"maintainerBlessed": true,
"reviewLink": "https://github.com/DefinitelyTyped/DefinitelyTyped/pull/46643/files",
"hasMergeConflict": false,
"authorIsOwner": false,
"isFirstContribution": true,
"popularityLevel": "Critical",
"newPackages": [],
"packages": [
"react"
],
"files": [
{
"path": "types/react/index.d.ts",
"kind": "definition",
"package": "react"
},
{
"path": "types/react/test/tsx.tsx",
"kind": "test",
"package": "react"
}
],
"hasDismissedReview": false,
"ciResult": "pass",
"lastReviewDate": "2020-08-19T13:42:07.000Z",
"reviewersWithStaleReviews": [],
"approvalFlags": 2,
"isChangesRequested": false
} |
🔔 @johnnyreilly @bbenezech @pzavolinsky @digiguru @ericanderson @DovydasNavickas @theruther4d @guilhermehubner @ferdaber @jrakotoharisoa @pascaloliv @Hotell @franklixuefei @Jessidhia @saranshkataria @lukyth @eps1lon @zieka @dancerphil @dimitropoulos @disjukr @vhfmag @hellatan — please review this PR in the next few days. Be sure to explicitly select |
@awmottaz The CI build failed! Please review the logs for more information. Once you've pushed the fixes, the build will automatically re-run. Thanks! |
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.
Big fan of the idea. What do you consider void about this component?
I think most the types maintainers agree that this should be the default in new major release of @types/react
so we might want to reflect that in the name.
types/react/test/index.ts
Outdated
}; | ||
|
||
const VoidFunctionComponent3: React.VoidFunctionComponent<SCProps> = | ||
// undesired: Rejects implicit usage of props.children |
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.
Since this component isn't supposed to accept children wouldn't the error be desired?
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.
Ah yes, sorry about the confusing verbiage here
@awmottaz One or more reviewers has requested changes. Please address their comments. I'll be back once they sign off or you've pushed new commits or comments. If you disagree with the reviewer's comments, you can "dismiss" the review using GitHub's review UI. Thank you! |
The naming is inspired by the analogy of "normal element" → |
Do you mean that the I could use some help with the tests. It's not clear to me what is causing the failure, and I saw failures when I ran the tests before adding my changes. |
Yes, we generally advise for that specific reason against using |
Just curious where that advice has been given? Maybe you can comment on #40993?
Yes, there is quite a lot that would probably break. For that reason, I think that a new type might be pragmatic and get something more useful to developers sooner and avoid the refactoring lift later. That change would force every |
@awmottaz The CI build failed! Please review the logs for more information. Once you've pushed the fixes, the build will automatically re-run. Thanks! |
Informal in https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/function_components#docsNav, various conversations in this repo etc. Though we probably should add a warning to the JSDOC and recommend |
👋 Hi there! I’ve run some quick measurements against master and your PR. These metrics should help the humans reviewing this PR gauge whether it might negatively affect compile times or editor responsiveness for users who install these typings. Let’s review the numbers, shall we? Comparison details 📊
It looks like nothing changed too much. I won’t post performance data again unless it gets worse. |
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.
Agree with the change and the naming makes sense to me now. React also uses that terminology:
input is a void element tag and must neither have
children
nor usedangerouslySetInnerHTML
.
We need to figure out what's wrong with CI though.
types/react/index.d.ts
Outdated
@@ -79,7 +79,7 @@ declare namespace React { | |||
* @deprecated Please use `ElementType` | |||
*/ | |||
type ReactType<P = any> = ElementType<P>; | |||
type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P>; | |||
type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P> | VoidFunctionComponent<P>; |
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.
This might cause CI to fail? Or is master
currently broken?
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.
master
seems to be currently broken
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.
Thanks, this does seem to be the problem. I'm trying it out now with just using VoidFunctionComponent here. Does this look okay to you?
type ComponentType<P = {}> = ComponentClass<P> | FunctionComponent<P> | VoidFunctionComponent<P>; | |
type ComponentType<P = {}> = ComponentClass<P> | VoidFunctionComponent<P>; |
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.
Ah, this is no good either. Going to try by reverting this line without VoidFunctionComponent
.
@awmottaz One or more reviewers has requested changes. Please address their comments. I'll be back once they sign off or you've pushed new commits or comments. If you disagree with the reviewer's comments, you can "dismiss" the review using GitHub's review UI. Thank you! |
@awmottaz Rebasing onto |
@awmottaz The CI build failed! Please review the logs for more information. Once you've pushed the fixes, the build will automatically re-run. Thanks! |
Confirmed that with latest |
@eps1lon would we be looking to deprecate VFC on the next major? Or just aliasing the FC type to VFC? |
Ready to merge |
I just published |
…nent type which does not accept "children" by @awmottaz Adds a type `VoidFunctionComponent` with `VFC` alias that is the same as the `FunctionComponent` (`FC`) type, except that it does not accept a `children` prop.
…nent type which does not accept "children" by @awmottaz Adds a type `VoidFunctionComponent` with `VFC` alias that is the same as the `FunctionComponent` (`FC`) type, except that it does not accept a `children` prop.
This is a really confusing choice of name. "void x" usually means "an x that returns nothing", and "accepting children" has no correlation to whether the component renders something or not. Is it too late to perhaps provide a better name (leaving the old one as an alias as needed, for compat)? Perhaps, like HTML, an element that takes no children should be called "self-closing"? |
Yeah, I wonder how this PR was merged with such a name, a disgrace to React Community commits a harakiri |
cc @eps1lon re #46643 (comment) |
We settled on "void component" since that is established terminology in React (e.g.
-- https://html.spec.whatwg.org/multipage/syntax.html#elements-2 So it does make sense to me to call them "VoidFunctionComponent" in the react domain. But I can see that this might clash with how we use "void" in javascript itself? We don't intend to keep the name around anyway. Maybe I'm misinterpreting the HTML spec but if you agree that "void" does make sense with respect to HTML I'd rather stick with the name (to not create even more type names) since it's temporary anyway. |
@eps1lon right but that's because it doesn't render its children. It still accepts them. This type is about props, not "what renders". In other words, I do not agree this naming makes sense in any arena. "void elements" are ones that do not render children. Components can accept or not accept children, and that has zero guaranteed correlation to whether they render children or not. |
If a component does not accept children it cannot render them. That is a guarantee. But I understand that components that do accept children do not guarantee that they render them e.g. Could you clarify how a |
Incorrect: function RendersChildrenButDoesNotAcceptChildren() {
return <div>children</div>;
} function AcceptsChildrenButDoesNotRenderChildren({ children }) {
return <input />;
} |
Which part is incorrect?
|
It renders children because the element it produces has children. "renders children" does not mean "renders the children prop it receives". function RendersChildrenAndAcceptsChildren({ children }) {
return <div>different children</div>
} Void elements render one thing with no children. For custom components, that is entirely decoupled from whether it accepts children as props or not. |
I find it hard to follow your point of view @ljharb, because for me this is not about what the component is rendering (that's precisely what the component is abstracting), but about how it's being used: |
@esebastian i totally agree, that's why i think "void element" is the wrong term - because that describes rendering behavior not interface behavior, and the type being used here describes the interface behavior. |
Seems like this naming originates from the HTML spec:
The quote above is about the input data type - one can't pass anything between the opening and closing tags to a "void" (in HTML spec terms) element. And then the spec goes on with
|
This is great! I switched everything to cross-posting my comment on the name from jsx-eslint/eslint-plugin-react#2913 (comment): (sorry for the “horrible” … I simply think that giving it a more generic name implying it’s a supertype of “FC” would have prevented a lot of confusion)
|
Adds a type
VoidFunctionComponent
withVFC
alias that is the same asthe
FunctionComponent
(FC
) type, except that it does not accept achildren
prop.cf. #40993
npm test
.)npm run lint package-name
(ortsc
if notslint.json
is present).tslint.json
containing{ "extends": "dtslint/dt.json" }
. If for reason the any rule need to be disabled, disable it for that line using// tslint:disable-next-line [ruleName]
and not for whole package so that the need for disabling can be reviewed.