-
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
Suggestion: type checking for JSX children #13618
Comments
@jwbay @RyanCavanaugh Did a quick prototype of this: joelday@50870c1 I'm sure there are a bunch of little gotchas here, but it's a start.
|
@joelday Oh, nice! Many thanks for taking at look at an implementation! |
@yuit Any traction with this? Would love for this to still make it into 2.3. Please let me know if there's anything I can do. |
Would also like to see this implemented! |
@joelday @petdun2519 PR will go up soon. Thanks for your protoype |
Tangentially related, but I wonder if there is a way to enforce that the |
This change has broken quite a few things for a patch release. The errors are not that helpful that I'm seeing, |
I've noticed this as well @cchamberlain , our code now looks like this: const { children, ...rest } = this.props;
return <Bla {...rest}>{children}</Bla>; |
@joscha - That did work for me in some of the instances I tried but there was at least one spot that when I tried it, it complained that the variable I was spreading did not contain an element I know TypeScript can't follow traditional semver without making most releases major versions, but this change breaks every component using spread and children (majority of our components) so seems like it warrants a minor version. |
Don't want to beat a dead horse but I just installed VS 2017 update 15.2 per #14529 (comment) and it only allows selection of TypeScript minor version, meaning I have to revert all the way back to Update: I got my solution working on 2.3, we had many instances of children being typed as the wrong type, causing this update to throw many errors. I very much like the typed children support, just feel that if a TypeScript release is not meant to strictly patch a previous release it should get a minor version, especially if the only thing we can specify in VS 2017 is minor version. |
Looking at #15160 (comment) it seems that the original idea of this issue isn't implemented and that the issue should be re-opened (imho). You can type your
But can't say that a That's because |
@donaldpipowitch agreed, the current implementation doesn't seem to work as advertised. |
The more I think of it I come to the conclusion that this could probably not be solved at a type checking level, because of the way TSX works currently. We can't use something like tagging enum FooterTag {}
type FooterElement = JSX.Element & FooterTag;
const Footer = () => <div>Footer.</div> as FooterElement;
interface ModalProps {
children: FooterElement;
}
const Modal = ({ children }: ModalProps) =>
<div>
{children}
</div>;
// `<Footer />` *needs* to be casted to `FooterElement`,
// because the return value is always `JSX.Element`
const UseModal = () =>
<Modal>
{<Footer /> as FooterElement}
</Modal>; When we useTSX the return value of our component will always be |
How could this happen?
|
Transpilation is done from JSX to "createElement" function calls and custom
implementations can return anything. I can declare function definition and
compiler can/should exactly know what return type will be.
…On Aug 8, 2017 8:39 AM, "Donald Pipowitch" ***@***.***> wrote:
How could this happen?
[image: image]
<https://user-images.githubusercontent.com/1152805/29057701-a71543a2-7c0c-11e7-88db-5edef0b77456.png>
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#13618 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AEAcnA_fYkJzzRqyyGGF09p61Rz9tXLLks5sV_SagaJpZM4LqJuY>
.
|
@donaldpipowitch Yui's left the team but was still assigned the issue. GitHub fixes this invalid assignment whenever someone makes any change (incl. comment) on an issue |
Couldn't JSX.Element be made generic with props/attributes? const i = <input value='42' />;
//yields JSX.Element<{ value: string }>
const c = <Component prop={ 42 } />
//yields JSX.Element<{ prop: number }> At this point the restricted children case devolves slightly from 'you can only pass something shaped like ModalFooter here' to 'you can only pass something with props shaped like ModalFooter's props', but for components I think that's really all that matters. |
Ah, I see. Thanks. So if you ever need someone new (remote)... 😏
As far as I understand this issue and what I personally would like to see is the first case ("you can only pass something shaped like ModalFooter here"), not the second case ("you can only pass something with props shaped like ModalFooter's props"). I want to enforce ordering "rules" of components similar to native DOM element ordering "rules". E.g. from
|
what has become of this issue, is it dead? |
I don't want to generate noise for the maintainers, but maybe we should just open a new issue for a focussed discussion and re-evaluation of this feature...? |
something like this is a mitigation: export interface IMenuPorps { children ? : any; } |
Curious about the status of this issue as well. Being able to restrict children to specific types would be very useful |
Chances are I misunderstood the issue topic, but I have somehow related problem. export interface MyProps {
extraElement: React.ReactNode;
}
class MyInnerComponent extends React.Component<MyProps> {
render(): React.ReactNode {
return (
<div>
{this.props.extraElement}
{this.props.children}
</div>
);
}
}
export default MyInnerComponent; Now I want to calculate children in another component. import MyInnerComponent, {MyProps as InnerComponentProps} from '...';
class MyWrapperComponent extends React.Component<{}> {
calculateProps(): InnerComponentProps {
return {
extraElement: <div>Hello!</div>,
children: [<div>First</div>, <div>Second</div>]
};
}
render(): React.ReactNode {
return (
<MyInnerComponent {...this.calculateProps()} />
);
}
} In this I get |
Recent discussion in this issue seems to be about allowing the JSX.Element type to be generic, or at least having JSX typing be more flexible. These use cases are covered by this issue, which is still open. I'd suggest moving all conversation there so that we can move toward an implementable proposal. |
#21699 should cover this scenario. |
Rationale
Props are an important part of a React component's interface, but children can be as well.
In applications it's not uncommon to want to restrict what kind of children a component will
accept. Currently this enforcement has to be done at runtime by throwing errors.
The Goal
Components can specify allowed children as a union type. Each member would correspond to
the tag, or 'type' field, of the resulting Element. Ideally this could be plucked from
the type of props.children, which would satisfy both component classes and SFCs.
Motivating Examples:
A modal component may want to make assumptions about its children to satisfy layout
constraints.
Similarly...
An interesting emerging pattern is using JSX as a function call to turn imperative APIs into
declarative ones. Currently these 'render callbacks' can't be type-checked at all. A more complete
summary can be found at http://reactpatterns.com/#render-callback. A further example can be found at https://github.com/ReactTraining/react-media#usage.
Lastly, I don't think any of this is necessarily specific to React. Other libraries leveraging the JSX
specification for component structure should be able to leverage this as well. The crux of this lies at
the relationship between the type of the 'children' attribute of a given tag and the children actually
passed to it at usage sites.
The text was updated successfully, but these errors were encountered: