Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[Master] Type checking JSX children#15160

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
yuit merged 24 commits intomasterfrommaster-jsxChildren
Apr 21, 2017
Merged

[Master] Type checking JSX children#15160

yuit merged 24 commits intomasterfrommaster-jsxChildren
Apr 21, 2017

Conversation

@yuit
Copy link
Contributor

@yuityuit commentedApr 12, 2017
edited
Loading

Fix#13618 : type checking children property (for examples and motivation see the original issue) Thanks@joelday for prototyping the feature!

Details

  • Look for "props" in JSX.ElementChildrenAttribute if there exist a property inside(by default in react.d.ts it ischildren) that property name will be used as a name of children property. If such property doesn't exist (e.g using older react.d.ts), we will just check all the children but will NOT attach the type as "children" property.

  • If there existed children in the body of JSX expression, synthesize symbol presenting those children and add them as part of JSX attributes namedchildren. If there alreadychildren specified as attribute of opening element there will be an error indicating that the attribute will get overwritten.

  • When we check each child, we call intocheckExpression what this mean is that all JSX Expression will have type JSX.Element. In the future, by treating as JSX.Element will allow us to easily extends for doing these works[JSX] Cannot declare JSX elements to be in specific types. #13746 orType JSX elements based on createElement function #14729.....

Examples

interfaceProp{a:number,b:string,children:string|JSX.Element}functionComp(p:Prop){return<div>{p.b}</div>;}// Error: missing childrenletk=<Compa={10}b="hi"/>;// Error: type not match// For this to work, "children: (string | JSX.Element)[]"letk1=<Compa={10}b="hi"><h2>Hello</h2>"hi"</Comp>// OKletk1=<Compa={10}b="hi"><h2>Hello</h2></Comp>;
interfaceIUser{Name:string;}interfaceIFetchUserProps{children:(user:IUser)=>JSX.Element;}classFetchUserextendsReact.Component<IFetchUserProps,any>{render(){returnthis.state            ?this.props.children(this.state.result)            :null;}}// ErrorfunctionUserName(){return(<FetchUser>{user=>(<h1>{user.NAme}</h1>//Thisisactuallyanerrornow;see.tests/baselines/reference/checkJsxChildrenProperty4.errors.txt)}</FetchUser>);}

Note: with the<Fetchuser> example, we can now provide contextual type and give completion as well (see fourslash test)

jwbay, Jessidhia, iammerrick, HerringtonDarkholme, tinganho, patrick91, minedeljkovic, dsifford, yortus, matijagrcic, and 4 more reacted with thumbs up emojijwbay, sean-vieira, Jessidhia, iammerrick, HerringtonDarkholme, patrick91, and utkarshsaxena93 reacted with hooray emojijwbay, asvetliakov, Jessidhia, iammerrick, HerringtonDarkholme, kimjoar, patrick91, BaconSoap, utkarshsaxena93, Hotell, and ulrichb reacted with heart emoji
IntrinsicClassAttributes: "IntrinsicClassAttributes"
};

const jsxChildrenPropertyName = "children";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

i would say we should treat this the same way we do withprops instead of hard coding it.

function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) {
const isComparingJsxAttributes = !!(source.flags & TypeFlags.JsxAttributes);
const containsSynthesizedJsxChildren = !!(source.flags & TypeFlags.ContainsSynthesizedJsxChildren);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

do not think we need this here

yuit reacted with thumbs up emoji
"category":"Error",
"code":2707
},
"props.children are specified twice. The attribute named 'children' will be overwritten.": {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

name forchildren should be variable, and i would not includeprops here.

@yuit
Copy link
ContributorAuthor

ping@RyanCavanaugh@mhegazy


let _jsxNamespace: string;
let _jsxFactoryEntity: EntityName;
let _jsxElementAttribPropInterfaceSymbol: Symbol; // JSX.ElementAttributesProperty [symbol]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

A comment would be good here

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

(A longer one explaining it, that is)

// interface ElementAttributesProperty {
// props: {
// children?: any;
// };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Let's figure out some other way to do this - this is too opaque and might not combine well with future work

yuit reacted with thumbs up emoji
error(attribsPropTypeSym.declarations[0], Diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, JsxNames.ElementAttributesPropertyNameContainer);
return undefined;
// No interface exists, so the element attributes type will be an implicit any
_jsxElementPropertiesName = undefined;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Doesn't this mean we'll keep doing this logic repeatedly?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Yep if we can't find the JSXElement. May be it is better to be empty string to indicate that we already done this

// If the call has correct arity, we will then check if the argument type and parameter type is assignable

const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call isincomplete
const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call isincoplete

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Undo spelling regression

}

exportfunctionisWhiteSpace(ch:number):boolean{
exportfunctionisWhiteSpaceLike(ch:number):boolean{

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Why the rename?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Because it is not just WhiteSpace but Whitespace and empty line.

@RyanCavanaugh
Copy link
Member

GTG after lint fixes

yuit and jwbay reacted with hooray emoji

@yuit
Copy link
ContributorAuthor

Thanks@RyanCavanaugh for reviewing 🍰 🍰

@yuityuit merged commita1a2006 intomasterApr 21, 2017
@yuityuit deleted the master-jsxChildren branchApril 21, 2017 17:02
@donaldpipowitch
Copy link
Contributor

Thank you! This is a great feature.

Strate reacted with thumbs up emoji

@RyanCavanaugh
Copy link
Member

@yuit can you write up some minimal docs? I can fill in some details but would like you to write down the basics

@radix
Copy link

The issue that this is meant to resolve has examples that restrict the type of the components in children, but I don't see an example in this PR that does that. Is it actually possible?

For example, in the linked issue there is a a use-case where aModal component only allowsModalHeader,ModalBody, orModalFooter components as children. Is that actually possible with this change?

@DanielRosenwasser
Copy link
Member

I see you've also been checking on SO:https://stackoverflow.com/questions/44475309/how-do-i-restrict-the-type-of-react-children-in-typescript-using-the-newly-adde

I think that the issue here is that all you really get back from a rendered component is a JSX Element. There's not really any information in thre to specify where the element came from. I'm not sure if@yuit or@RyanCavanaugh have had any thoughts on this.

@radix
Copy link

yeah, I have become skeptical that what I'm trying to do is possible, which makes me think that#13618 should not have been closed, since it is specifically about getting type restrictions on what kind of components are used as children of a react component. But I could very well be missing something!

@donaldpipowitch
Copy link
Contributor

donaldpipowitch commentedJun 12, 2017
edited
Loading

I think that the issue here is that all you really get back from a rendered component is a JSX Element. There's not really any information in thre to specify where the element came from.

Yeah, this is what I saw inmy tests, too. You can't say something like this:

importReact,{Component}from'react';import{render}from'react-dom';classFooextendsComponent<{},void>{render(){return<p>Hello from Foo!</p>;}}interfaceBarProps{children?:Foo|Array<Foo>;}constBar=({ children}:BarProps)=><div>This must be Foo(s):{children}.</div>;render(<div><Bar><Foo/>{/* invalid - is treated as `JSX.Element`, not `Foo` */}</Bar></div>,document.getElementById('app'));
KonradKlimczak reacted with confused emoji

@radix
Copy link

If this really can't be done, then I suggest re-opening#13618, since it's specifically about typing the components used as children (should I comment as such there?)

donaldpipowitch, Hotell, kgroat, and zackify reacted with thumbs up emoji

@Hotell
Copy link

any "last words" on this folks ?

If this really can't be done, then I suggest re-opening#13618, since it's specifically about typing the components used as children (should I comment as such there?)

cc@yuit@DanielRosenwasser@RyanCavanaugh thx!

kgroat and otbe reacted with thumbs up emoji

@zackify
Copy link

Would love to see support for typing children! 👍

HaNdTriX and jonmilner reacted with thumbs up emoji

@microsoftmicrosoft locked and limited conversation to collaboratorsJun 21, 2018
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@RyanCavanaughRyanCavanaughRyanCavanaugh left review comments

+1 more reviewer

@mhegazymhegazymhegazy left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

10 participants

@yuit@RyanCavanaugh@donaldpipowitch@radix@DanielRosenwasser@Hotell@zackify@mhegazy@msftclas

[8]ページ先頭

©2009-2025 Movatter.jp