Skip to content

Using lookahead to detect generic JSX elements? #6395

@dead-claudia

Description

@dead-claudia

Initially from a couple different comments, but elaborated here.

Currently, in order to use a generic JSX element, you must alias both the type and interface to a non-generic specialization.

class Select<T> extends React.Component<SelectProps<T>, any> {}

// Alias
type StringSelect = new () => Select<string>
const StringSelect = <StringSelect> Select

const Form = () => <StringSelect items={['a','b']} />

It would be a lot more convenient and consistent to use something like this:

const Form = () => <Select<string> items={['a', 'b']} />

In order to differentiate the latter, you can use a single token of lookahead in the parser to know if it's a generic JSX element:

  • If the next token is a <, like in < Select <, then consume the rest of the type as a generic type. After consuming that:
    • If the next token is a >, then finish the type as a generic type cast.
    • If the next token is an identifier or a { (for spread attributes, when they get implemented), then parse the rest as a JSX element.
    • Otherwise, parse the rest as a type cast.
  • If the next token is a >, like in < Select >, then finish the type as a simple type cast.
  • If the next token is an identifier or a {, then parse the rest as a JSX element.
  • Otherwise, consume the rest as a type cast.

I don't know of any reason that wouldn't be feasible to do, considering async arrow functions, which are already implemented, require potentially a whole call expression of parsing to differentiate between let f = async (x, y), which is a call expression, and let f = async (x, y) => x, which is an async arrow function. (I feel sorry for whoever ends up implementing that in V8, which doesn't support any backtracking or much lookahead for memory reasons.)

/cc @RyanCavanaugh

Metadata

Metadata

Assignees

Labels

Domain: JSX/TSXRelates to the JSX parser and emitterEffort: DifficultGood luck.FixedA PR has been merged for this issueHelp WantedYou can do thisSuggestionAn idea for TypeScript

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions