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

TS + JSX users should be always using class components only, and this needs to be documented. #9

Open
dead-claudia opened this issue May 27, 2023 · 2 comments

Comments

@dead-claudia
Copy link
Member

TypeScript has slow-walked for years requests to add support for JSX components that 1. are functions (not classes) and 2. return anything other than a JSX.Element value. It's long interfered with React types as well, which only makes this more baffling.

They've even for longer resisted adding support for non-function, non-class components, and the chances of those getting in are probably extremely slim IMHO.

The current long-standing recommendation I've given out for years for TS + JSX users is this: use class components exclusively. It's the only way to make the TS type checker happy. This needs to be included in the documentation.

@dead-claudia
Copy link
Member Author

They did eventually merge microsoft/TypeScript#51328, but that was only just more than a month ago. We might be able to use that to allow object components and closure components in JSX, but that'll require some testing. In particular, generic closure components defined via it will need tested for.

@markwylde
Copy link

I managed to get it working by adding a mithril.d.ts file into my project:

import * as m from 'mithril';

declare global {
  namespace JSX {
    // Represents a Mithril Vnode.
    interface Element extends m.Vnode<any, any> {}
    // Specifies the property used for component attributes.
    interface ElementAttributesProperty { attrs: {}; }
    // Defines what can be used as an element type in JSX.
    type ElementType =
      // String tags, e.g., "div", "span".
      | string
      // Function components: simple functions returning a Vnode.
      | ((vnode: m.Vnode<any, any>) => m.Vnode<any, any> | null)
      // Closure components: functions returning an object with a view function.
      | ((vnode: m.Vnode<any, any>) => { view: (vnode: m.Vnode<any, any>) => m.Vnode<any, any> | null | void })
      // Object components: directly use objects with a view method as components.
      | { view: (vnode: m.Vnode<any, any>) => m.Vnode<any, any> | null | void }
      // Class components: not as common in Mithril, but included for completeness.
      | (new (props: any) => any);
  }
}

It's only let's me define components like this though:

const TestComponent = () => ({
  view: ({ attrs }) => {

Not like:

const TestComponent = {
  view: ({ attrs }) => {

@dead-claudia dead-claudia transferred this issue from MithrilJS/mithril.js Sep 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants