-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Allow overloading of JSX element constructors #29025
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
Comments
I just tested it out and it works on my instance of 3.2, with a few interesting quirks (though they are all VSCode related but probably also related to the autocomplete list given by the compiler):
Those are low priority though, and it looks like it works well with overloading the constructors on class components, so that's pretty awesome to see! |
Revisiting this, it looks like the overload signature works for function-type components, but is failing for class-type components, such as this example: function isPropsForAnchorElement(props: ButtonProps | AnchorProps): props is AnchorProps {
return 'href' in props
}
class Clickable extends React.Component<ButtonProps | AnchorProps> {
constructor(props: ButtonProps)
constructor(props: AnchorProps)
constructor(props: ButtonProps | AnchorProps) {
super(props)
}
render() {
if (isPropsForAnchorElement(this.props)) {
return <a { ...this.props } />
} else {
return <button { ...this.props } />
}
}
}
const aClickable = <Clickable href='abc' onClick={event => {}} /> // implicit 'any' on event
const btnClickable = <Clickable onClick={event => {}} /> // implicit 'any' on event I'm assuming it's because it's using the |
Yup. The irony is that if that jsx namespace member isn't present, we'll use the parameter type, just like functions nowadays. |
I wonder if it's better to just remove that specific interface in the JSX namespace then 🤔 I think this answers all my questions for now, thanks for the help! |
I just ran into this. @ferdaber What needs to happen so we can support overloading class components? I need this to define the correct types of react-autosuggest. |
Removing the |
Is this something we need to fix upstream in the React types, or are you suggesting doing this by patching the types locally? |
Either will work, but if you choose to patch it it does need to be a literal patch, since you can't remove declarations via declaration merging |
Thinking about this some more, why do you need overloads in your class example? Isn't the union parameter sufficient? Related: https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html#use-union-types |
Union parameter types are subtly different, and it may be a bug honestly (unsure). Consider the following: type AElement = HTMLAnchorElement
type BElement = HTMLButtonElement
interface A {
a: 'a'
onClick(el: AElement): void
}
interface B {
onClick(el: BElement): void
}
declare function AorB(props: A | B): JSX.Element
declare function AorBOverload(props: A): JSX.Element
declare function AorBOverload(props: B): JSX.Element
// TS error: `el` is inferred to be `any` even though it should be narrowed to `AElement`
const foo = <AorB a='a' onClick={el => {}} />
// this works fine and `el` is inferred to be `AElement`
const bar = <AorBOverload a='a' onClick={el => {}} /> |
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: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:
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:
The text was updated successfully, but these errors were encountered: