Skip to content
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

Allow an interface in the JSX namespace to specify the element class type #14789

Open
LennyLixalot opened this issue Mar 22, 2017 · 9 comments
Open
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@LennyLixalot
Copy link

We're writing a non-react library that uses TS's JSX support with custom interfaces defined in the JSX namespace. Unless we are very much mistaken (The documentation seems a little out-of-date in this area? Most of our current understanding comes from reading through issues on here, we may have missed something.) it seems that while ElementClass can be used to define the type of the element instance type there is no interface to limit the members of the element class type.

We have a custom component base-class and an equivalent to React's createElement function. Our createElement function needs to be able to create instances of the component classes. To be able to do this in a type-safe manner, we need to be able to specify an interface for the element class type that can require a specific constructor signature.

This feels like an oversight in the current implementation TBH. With React itself it's even possible to create components with incompatible constructors that would fail at runtime.

@RyanCavanaugh
Copy link
Member

Can you provide some example code so I can verify I'm understanding what you're saying?

@RyanCavanaugh
Copy link
Member

Basically you want JSX.ElementClass, except for the constructor function type typeof X in the expression <X /> in addition to the current checking which checks the instance type X ?

@LennyLixalot
Copy link
Author

Yes, exactly that.

Unless we've misunderstood something fundamental about how this whole JSX thing is working (we're .NET devs a little out of our comfort-zones, it's possible), the createElement function is called with typeof X as the first argument, and in order to really do anything useful with it we need to create an instance of X. If we could control the syntax of the constructor we would be able to do this in a reliable and type-safe manner.

For our particular use-case we'd probably want something like

type ComponentConstructor<TProps> = new (props: TProps) => Component<TProps>

or maybe

type ComponentConstructor<TComponent extends Component<TProps>, TProps> = new (props: TProps) => TComponent

Slightly simplified example of course.

@LennyLixalot
Copy link
Author

Note the plan would be to have our base-class implement this constructor and assign the props as required, so in most cases the component classes wouldn't even need to do anything with constructors at all, but if they did they'd be forced to comply.

@RyanCavanaugh RyanCavanaugh added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels Mar 22, 2017
@RyanCavanaugh
Copy link
Member

Seems reasonable to think about. We didn't implement anything like this earlier simply because React components almost never override their base class constructor, thus there's little chance for error.

@LennyLixalot
Copy link
Author

If we could get this and #13618 (setting limits on children) then this feature would feel much more complete and applicable to a larger-range of DSL-use-cases.

@dead-claudia
Copy link

BTW, Mithril needs this for TS users to be able to use anything besides classes for components if they use JSX. And we have a lot of components that aren't - a lot of people prefer either object or closure components, and even our docs don't just use class components.

This is basically a blocker for us to support JSX in TS in any real capacity, if that helps explain a good use case for adding this feature.

For us, something as simple as type ElementType<P> = ... would work. (We can't use an interface, since we need a union here.) The return type is just the name of a valid component type for a factory.

@dead-claudia
Copy link

BTW, we do support JSX in JS, so TS is the odd one out here. Just thought I'd clarify.

@dead-claudia
Copy link

@RyanCavanaugh Do you have any status update on this? I know it's a bit of an old bug.

askvortsov1 added a commit to flarum/framework that referenced this issue Dec 13, 2021
Unfortunately, TypeScript only supports strings and classes for JSX tags.
Therefore, our type definition should only allow for those two types.
see microsoft/TypeScript#14789 (comment)
askvortsov1 added a commit to flarum/framework that referenced this issue Dec 14, 2021
Unfortunately, TypeScript only supports strings and classes for JSX tags.
Therefore, our type definition should only allow for those two types.
see microsoft/TypeScript#14789 (comment)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants