Skip to content

Declare web component in solid typescript #616

Closed

Description

@nemixe

have been tried implement web component in solid typescript but i dont really know how to declare the component name, it show an error like this.

CleanShot 2021-08-23 at 08 36 54@2x

i have tried to declare it on file declaration.d.ts like this.

CleanShot 2021-08-23 at 08 37 56@2x

is there any way to declare web component name in solid typescript ?, thanks!.

Activity

  1. ryansolid commented on Aug 23, 2021

    @ryansolid
    Member

    I think the problem is that works on the global namespace and it needs to work on Solid's. I've done it the way posted above in the past but that was back when we were too polluting the global namespace like React.

    So perhaps:

    declare module "solid-js" {
      namespace JSX {
        interface IntrinsicElements {
          "component1-component": any
        }
      }
    }
  2. nemixe commented on Aug 23, 2021

    @nemixe
    Author

    thanks for your reply. so i've implement it and now it shows different error like this.

    CleanShot 2021-08-23 at 11 36 35@2x

    this is my declaration.d.ts file look like.
    CleanShot 2021-08-23 at 11 38 49@2x

  3. nemixe commented on Aug 23, 2021

    @nemixe
    Author

    but i found out if i declare it on component file like this.

    CleanShot 2021-08-23 at 16 09 12@2x

    this works, but i dont know if this is a good practice or not.

  4. ryansolid commented on Aug 23, 2021

    @ryansolid
    Member

    Honestly, TypeScript differentiating between this confuses me. Anyone with TS experience with custom elements can chime in. @trusktr maybe.

  5. rturnq commented on Aug 23, 2021

    @rturnq
    Member

    You should be able to perform this module augmentation in a declaration file (.d.ts) which will make it available everywhere in your app. The trick is to also import 'solid-js' in that declaration file. Without the import, the new module declaration clobbers the existing one instead of extending it. Here is an example: https://codesandbox.io/s/solid-counter-forked-ulhhj?file=/my-web-components.d.ts

    Please also note codesandbox falls down sometimes dealing with this stuff - reloading usually fixes it.

  6. nemixe commented on Aug 24, 2021

    @nemixe
    Author

    works perfectly, thanks!.

  7. hawkticehurst commented on Jun 1, 2022

    @hawkticehurst

    Chiming in with a potential improvement on the ideas/code snippets in this thread:

    There was a discussion/thread in a WC library called Shoelace on how to use the components in Solid.

    As part of that discussion, @justinfagnani (a member of the Lit team at Google) offered the below declaration file snippet as a way to get even better type annotations on web components used in Solid.

    I figured out how to get good typings for all custom elements that are added to HTMLElementTagNameMap without having to add each individually to 'solid-js'.JSX.IntrinsicElements and without using any for the type.

    declare module 'solid-js' {
      namespace JSX {
        type ElementProps<T> = {
          // Add both the element's prefixed properties and the attributes
          [K in keyof T]: Props<T[K]> & HTMLAttributes<T[K]>;
        }
        // Prefixes all properties with `prop:` to match Solid's property setting syntax
        type Props<T> = {
          [K in keyof T as `prop:${string & K}`]?: T[K];
        }
        interface IntrinsicElements extends ElementProps<HTMLElementTagNameMap> {
        }
      }
    }

    You can see in the Solid playground that an element with foo: number causes an error with a binding of prop:foo={'hello'}, which is what we want:

    Solid Playground Link

    ^(Link to Justin's comment for more context)

    It's also worth noting, however, that this will only work for web component libraries that add their components to the global HTMLElementTagNameMap interface as demonstrated in the above Solid playground link. This is something that Shoelace does for its components, but you'll want to check your desired component library for this addition.

    Hope it helps anyone still passing by on this thread!

  8. AlexErrant commented on Aug 17, 2022

    @AlexErrant
    Contributor

    If you extend 'solid-js'.Component (instead of HTMLElement as above), here's some half-working code:

    declare module "solid-js" {
      namespace JSX {
        type ElementProps<T> = {
          [K in keyof T]: T[K] extends Component<infer P> ? P : never
        }
    
        interface IntrinsicElements extends ElementProps<HTMLElementTagNameMap> {}
      }
    }

    Unfortunately this code does not error if you pass props to a component that has no props, like function MyComp(): JSX.Element { ... }. Unfortunately I'm not good enough at TypeScript to figure out the solution. Some thoughts on where I gave up:

    The default generic on Component is {}, which I can't differentiate from a populated prop using conditional types. In other words:

        type ElementProps<T> = {
          [K in keyof T]: T[K] extends Component<infer P>
            ? P extends Record<string, never>
              ? boolean // this is never hit
              : P
            : never // though this is hit, which correctly yields errors if, say, you pass a string to an number prop
        }

    For now I think I'll just have two HTMLElementTagNameMaps - one for Components with props, and one for Components without props. I haven't tried it yet though.

  9. nilshelmig commented on Jul 24, 2024

    @nilshelmig

    @ryansolid Any plans or information to support this in solidjs? Or at least a documentation note, that using web components with typescript requires this?

  10. ryansolid commented on Jul 24, 2024

    @ryansolid
    Member

    There was a documentation note at one point about what I posted above. But, looking now it doesn't seem to have made it to the new Docs. So I think there could be a note about how to declare web components in the TS section.

    Opened an issue: solidjs/solid-docs#823

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    typescriptrelating to typescript or types

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions