Description
Search Terms
jsx overload conditional component react
Suggestion
Allow for some kind of overload mechanism for JSX element construction, that is: determine contextual types for the allowable attributes for a JSX expression based on attributes already passed in.
Use Cases
There are times when we want to conditionally render based on the type of a certain property in a props object, or the existence/non-existence of a certain property in a props object. A very common use case is rendering clickable elements as anchor tags if a href
attribute is present:
type AnchorProps = JSX.IntrinsicElements['a']
type ButtonProps = JSX.IntrinsicElements['button']
declare function Buttonish(props: ButtonProps): JSX.Element
declare function Buttonish(props: AnchorProps): JSX.Element
declare function Buttonish(props: AnchorProps | ButtonProps): JSX.Element
const myAnchor = <Buttonish href="typescriptlang.org" onClick={event => {}} />
// `event` is inferred to be React.MouseEvent<HTMLAnchorElement> because `href` is already there
The above is one suggestion though I don't know we could resolve that with class-based components.
I know right now that this is partially solved with generic components + conditional types, but it's kind of odd DX:
type EitherProps<T> = T extends string ? { href?: T } & AnchorProps : { href?: undefined } & ButtonProps
declare function Buttonish<T>(props: EitherProps<T>): JSX.Element
const myAnchor = <Buttonish href="typescriptlang.org">
// generic type inferred, but looks weird since T = string which doesn't tell you much
Examples
Unsure what the best approach would be. I think one good DX I was hoping for was for the autocomplete list to be narrowed as attributes are added to a JSX expression, when the compiler gets more contextual information to infer, so that after href
is added in the above example, the event handlers are narrowed to just be handlers related to anchor elements, for example.
Checklist
My suggestion meets these guidelines:
- This wouldn't be a breaking change in existing TypeScript/JavaScript code
- This wouldn't change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
- This feature would agree with the rest of TypeScript's Design Goals.