GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — [Master] Type checking JSX children by yuit · Pull Request #15160 · microsoft/TypeScript

Conversation

@yuit

@yuit Yui (yuit) commented Apr 12, 2017 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

Fix #13618 : type checking children property (for examples and motivation see the original issue) Thanks Joel Day (@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 is children) 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 named children. If there already children 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 into checkExpression 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 or Type JSX elements based on createElement function #14729.....

Examples

interface Prop {
    a: number,
    b: string,
    children: string | JSX.Element
}

function Comp(p: Prop) {
    return <div>{p.b}</div>;
}

// Error: missing children
let k = <Comp a={10} b="hi" />;
// Error: type not match
// For this to work, "children: (string | JSX.Element)[]"
let k1 = <Comp a={10} b="hi">
    <h2>Hello</h2> "hi"
</Comp>

// OK
let k1 = <Comp a={10} b="hi">
    <h2>Hello</h2>
</Comp>
;
interface IUser {
    Name: string;
}

interface IFetchUserProps {
    children: (user: IUser) => JSX.Element;
}

class FetchUser extends React.Component<IFetchUserProps, any> {
    render() {
        return this.state
            ? this.props.children(this.state.result)
            : null;
    }
}

// Error
function UserName() {
    return (
        <FetchUser>
            { user => (
                <h1>{ user.NAme }</h1>   // This is actually an error now; 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)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

jwbay, Jessidhia, iammerrick, HerringtonDarkholme, tinganho, patrick91, minedeljkovic, dsifford, yortus, matijagrcic, and 4 more reacted with thumbs up emoji jwbay, sean-vieira, Jessidhia, iammerrick, HerringtonDarkholme, patrick91, and utkarshsaxena93 reacted with hooray emoji jwbay, asvetliakov, Jessidhia, iammerrick, HerringtonDarkholme, kimjoar, patrick91, BaconSoap, utkarshsaxena93, Hotell, and ulrichb reacted with heart emoji
All reactions
  • 👍 14 reactions
  • 🎉 7 reactions
  • ❤️ 11 reactions
Kanchalai Tanglertsampan added 11 commits April 7, 2017 16:41
Kanchalai Tanglertsampan
Wip - type checking JSX children
b3846bf
Kanchalai Tanglertsampan
Consider whitespace that won't be emitted to be different kind so tha…
f86a730
…t we won't include in typ-checking
Kanchalai Tanglertsampan
Use JSX Attributes to contextually type children property
8e2dd38
Kanchalai Tanglertsampan
Format checker
17417e9
Kanchalai Tanglertsampan
Store scanning information whether JSXText is just an all whitespaces
4562fd0
Kanchalai Tanglertsampan
wip-fixing consuming whitespace in children
c1ea303
Kanchalai Tanglertsampan
Fixing consuming whitespace in children
4fa2312
Kanchalai Tanglertsampan
Add tests
f099046
Kanchalai Tanglertsampan
update baselines
eb0ad7f
Kanchalai Tanglertsampan
Merge branch 'master-jsxChildren' of https://github.com/Microsoft/Typ…
e5b95fc
…eScript into master-jsxChildren

# Conflicts:
#	src/compiler/scanner.ts
Kanchalai Tanglertsampan
Fix linting error
012f459
@yuit
Yui (yuit) requested a review from Ryan Cavanaugh (RyanCavanaugh) April 12, 2017 20:11
@msftclas Microsoft Contribution License Agreements (msftclas) added the cla-not-required label Apr 12, 2017
Kanchalai Tanglertsampan
Add tests and update baselines
58e2189
mhegazy
Mohamed Hegazy (mhegazy) reviewed Apr 13, 2017
View reviewed changes
Comment thread src/compiler/checker.ts Outdated
IntrinsicClassAttributes: "IntrinsicClassAttributes"
};

const jsxChildrenPropertyName = "children";

@mhegazy Mohamed Hegazy (mhegazy) Apr 13, 2017

Copy link
Copy Markdown
Contributor

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.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread src/compiler/checker.ts Outdated
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);

@mhegazy Mohamed Hegazy (mhegazy) Apr 13, 2017

Copy link
Copy Markdown
Contributor

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.

do not think we need this here

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

yuit reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
Comment thread src/compiler/diagnosticMessages.json Outdated
"category": "Error",
"code": 2707
},
"props.children are specified twice. The attribute named 'children' will be overwritten.": {

@mhegazy Mohamed Hegazy (mhegazy) Apr 13, 2017

Copy link
Copy Markdown
Contributor

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.

name for children should be variable, and i would not include props here.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Kanchalai Tanglertsampan added 8 commits April 14, 2017 15:21
Kanchalai Tanglertsampan
Remove a flag indicating the children is synthesized..We will give an…
bb8bab3
… error if you use children without specified such property
Kanchalai Tanglertsampan
Read "children" property from react DTS file
c778a48
Kanchalai Tanglertsampan
Update tests and baselines
dbf2a96
Kanchalai Tanglertsampan
Update baselines and tests (2)
9a23b75
Kanchalai Tanglertsampan
Fix linting error
7829cba
Kanchalai Tanglertsampan
Update error message to use variable name for "children"
d290cf7
Kanchalai Tanglertsampan
Merge branch 'master' into master-jsxChildren
f6f0813
# Conflicts:
#	src/compiler/checker.ts
#	src/compiler/diagnosticMessages.json
Kanchalai Tanglertsampan
Fix baselines and linting error from merging with master
c13383a
@yuit

Yui (yuit) commented Apr 17, 2017

Copy link
Copy Markdown
Contributor Author

ping Ryan Cavanaugh (@RyanCavanaugh) Mohamed Hegazy (@mhegazy)

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) reviewed Apr 18, 2017
View reviewed changes
Comment thread src/compiler/checker.ts Outdated

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

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Apr 18, 2017

Copy link
Copy Markdown
Member

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.

A comment would be good here

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Apr 18, 2017

Copy link
Copy Markdown
Member

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.

(A longer one explaining it, that is)

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) reviewed Apr 18, 2017
View reviewed changes
Comment thread src/compiler/checker.ts Outdated
// interface ElementAttributesProperty {
// props: {
// children?: any;
// };

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Apr 18, 2017

Copy link
Copy Markdown
Member

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.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

yuit reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) reviewed Apr 18, 2017
View reviewed changes
Comment thread src/compiler/checker.ts Outdated
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;

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Apr 18, 2017

Copy link
Copy Markdown
Member

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.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@yuit Yui (yuit) Apr 18, 2017

Copy link
Copy Markdown
Contributor Author

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.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) reviewed Apr 18, 2017
View reviewed changes
Comment thread src/compiler/checker.ts Outdated
// 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 is incomplete
const callIsIncomplete = node.attributes.end === node.end; // If we are missing the close "/>", the call is incoplete

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Apr 18, 2017

Copy link
Copy Markdown
Member

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.

Undo spelling regression

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
RyanCavanaugh
Ryan Cavanaugh (RyanCavanaugh) reviewed Apr 18, 2017
View reviewed changes
Comment thread src/compiler/scanner.ts
}

export function isWhiteSpace(ch: number): boolean {
export function isWhiteSpaceLike(ch: number): boolean {

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) Apr 18, 2017

Copy link
Copy Markdown
Member

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.

Why the rename?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@yuit Yui (yuit) Apr 18, 2017

Copy link
Copy Markdown
Contributor Author

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.

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

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Yui T
Change how we look up children attribute from react.d.ts
e9cd3ad
Yui T added 2 commits April 19, 2017 22:33
Yui T
Update tests and baselines
b7a30c1
Yui T
Fix spelling and add comment
e03be45
@RyanCavanaugh

Ryan Cavanaugh (RyanCavanaugh) commented Apr 20, 2017

Copy link
Copy Markdown
Member

GTG after lint fixes

yuit and jwbay reacted with hooray emoji
All reactions
  • 🎉 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Kanchalai Tanglertsampan
Fix linting
e7e13ec
@yuit

Yui (yuit) commented Apr 21, 2017

Copy link
Copy Markdown
Contributor Author

Thanks Ryan Cavanaugh (@RyanCavanaugh) for reviewing 🍰 🍰

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@yuit
Yui (yuit) merged commit a1a2006 into master Apr 21, 2017
@yuit
Yui (yuit) deleted the master-jsxChildren branch April 21, 2017 17:02
@aaronjensen Aaron Jensen (aaronjensen) mentioned this pull request Apr 21, 2017
property children not found in props of React element ... meta/flow#1964
Closed
@donaldpipowitch

Donald Pipowitch (donaldpipowitch) commented Apr 21, 2017

Copy link
Copy Markdown
Contributor

Thank you! This is a great feature.

Strate reacted with thumbs up emoji
All reactions
  • 👍 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@RyanCavanaugh

Ryan Cavanaugh (RyanCavanaugh) commented Apr 24, 2017

Copy link
Copy Markdown
Member

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

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@lostfictions six (lostfictions) mentioned this pull request Apr 29, 2017
Move TypeScript defs to own folder and add tests react-grid-layout/react-draggable#245
Merged
@firewave-remo Remo Fischer (firewave-remo) mentioned this pull request May 4, 2017
Error on type checking JSX children #15583
Closed
@yuit Yui (yuit) mentioned this pull request May 4, 2017
[React] Include ElementChildrenAttribute for 2.3 DefinitelyTyped/DefinitelyTyped#16327
Merged
15 tasks
@radix

Christopher Armstrong (radix) commented Jun 10, 2017

Copy link
Copy Markdown

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 a Modal component only allows ModalHeader, ModalBody, or ModalFooter components as children. Is that actually possible with this change?

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@DanielRosenwasser

Daniel Rosenwasser (DanielRosenwasser) commented Jun 11, 2017

Copy link
Copy Markdown
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 Yui (@yuit) or Ryan Cavanaugh (@RyanCavanaugh) have had any thoughts on this.

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@radix

Christopher Armstrong (radix) commented Jun 11, 2017

Copy link
Copy Markdown

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!

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@donaldpipowitch

Donald Pipowitch (donaldpipowitch) commented Jun 12, 2017 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Contributor

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 in my tests, too. You can't say something like this:

import React, { Component } from 'react';
import { render } from 'react-dom';

class Foo extends Component<{}, void> {
  render() {
    return <p>Hello from Foo!</p>;
  }
}

interface BarProps {
  children?: Foo | Array<Foo>;
}

const Bar = ({ 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
All reactions
  • 😕 1 reaction

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@radix

Christopher Armstrong (radix) commented Jun 12, 2017

Copy link
Copy Markdown

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
All reactions
  • 👍 4 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@donaldpipowitch Donald Pipowitch (donaldpipowitch) mentioned this pull request Jun 12, 2017
Suggestion: type checking for JSX children #13618
Closed
@Hotell

Martin Hochel (Hotell) commented Jul 15, 2017

Copy link
Copy Markdown

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 Yui (@yuit) Daniel Rosenwasser (@DanielRosenwasser) Ryan Cavanaugh (@RyanCavanaugh) thx!

kgroat and otbe reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@zackify

Zach Silveira (zackify) commented Oct 2, 2017

Copy link
Copy Markdown

Would love to see support for typing children! 👍

HaNdTriX and jonmilner reacted with thumbs up emoji
All reactions
  • 👍 2 reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@microsoft Microsoft (microsoft) locked and limited conversation to collaborators Jun 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Reviewers

@RyanCavanaugh Ryan Cavanaugh (RyanCavanaugh) RyanCavanaugh left review comments
+1 more reviewer
@mhegazy Mohamed Hegazy (mhegazy) mhegazy left review comments
Reviewers whose approvals may not affect merge requirements

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

9 participants

@yuit @RyanCavanaugh @donaldpipowitch @radix @DanielRosenwasser @Hotell @zackify @mhegazy @msftclas
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.