Skip to content

bug: Stencil Generated components.d.ts Missing Kebab-Case Property Typings in HTML Element Interfaces #6194

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

Open
3 tasks done
BenjaminBrossi opened this issue Mar 12, 2025 · 4 comments

Comments

@BenjaminBrossi
Copy link

Prerequisites

Stencil Version

4.27.2

Current Behavior

Bug Ticket

Description

The Stencil compiler generates a components.d.ts file that defines component interfaces using camelCase property names in the Components namespace, but fails to include kebab-case alternatives in the HTML element interfaces. This causes type errors when using the web components in React or other frameworks that use kebab-case attribute names in JSX.

Current Behavior

Currently, the generated components.d.ts file:

  1. Defines component properties in camelCase within the Components namespace:

    export namespace Components {
      interface MdxProductCard {
        "availability"?: "available" | "unavailable" | "disabled";
        "brand"?: string;
        "discountPrice"?: number;
        // other properties...
      }
    }
  2. HTML element interfaces extend the Components interfaces:

    interface HTMLMdxProductCardElement extends Components.MdxProductCard, HTMLStencilElement {
      // event listeners...
    }
  3. The React and Stencil JSX typings need to be manually added with a custom script to support kebab-case attributes:

    declare module "react" {
      export namespace JSX {
        interface IntrinsicElements {
          "mdx-product-card": {
            "discount-price"?: number | string;
            "discountPrice"?: number | string;
            // other properties...
          };
        }
      }
    }

Expected Behavior

Expected Behavior

The Stencil compiler should automatically generate HTML element interfaces that support both camelCase and kebab-case property names:

  1. The Components namespace should continue to use camelCase for TypeScript usage.

  2. The HTML element interfaces should support both camelCase and kebab-case attributes:

    interface HTMLMdxProductCardElement extends Components.MdxProductCard, HTMLStencilElement {
      // Add support for kebab-case attributes
      "discount-price"?: number;
      // existing camelCase properties from Components.MdxProductCard
      // event listeners...
    }
  3. The React and Stencil JSX typings should be automatically generated with both camelCase and kebab-case attributes.

System Info

Steps to Reproduce

Steps to Reproduce

  1. Create a Stencil component with camelCase properties:

    @Component({ tag: "my-component" })
    export class MyComponent {
      @Prop() discountPrice: number;
    }
  2. Build the component library with stencil build

  3. Examine the generated components.d.ts file

  4. Try to use the component in React with kebab-case attributes:

    <my-component discount-price={5} />
  5. Observe TypeScript errors because the kebab-case attribute is not defined in the typings.

Code Reproduction URL

https://github.com/BenjaminBrossi/stencil-typings

Additional Information

Impact

This issue forces teams to create and maintain custom scripts to generate proper typings for React and other frameworks. Without these scripts, developers experience type errors when using kebab-case attributes in JSX, even though the web components themselves accept these attributes at runtime.

Environment

  • Stencil version: 4.27.2
  • TypeScript version: 5.7.3
  • React version: 19

Workaround

We currently use a custom script to generate proper typings for React and Stencil JSX. This script:

  1. Extracts all component properties from the generated components.d.ts
  2. Converts camelCase properties to kebab-case
  3. Generates React and Stencil JSX module declarations with both camelCase and kebab-case properties
  4. Appends these declarations to the components.d.ts file

This workaround is maintenance-intensive and should be unnecessary if Stencil properly supported kebab-case attributes in its generated typings.

@christian-bromann
Copy link
Member

As mentioned in the docs:

When we use our component in a TSX file, an attribute uses camelCase

as well as:

In HTML, the attribute must use 'dash-case'

I would actually consider it a bug that kebab case works in JSX, Stencil was never suppose to support it. Can you please elaborate why you prefer kebab casing in your use case? Are your users using raw Stencil components in React applications? Are you suggesting that requiring camelCase in JSX and kebab case in HTML is confusing?

@BenjaminBrossi
Copy link
Author

The Problem is, that we have customers, that want that typing in JSX-Files, without using the react wrapped components.

@dgonzalezr
Copy link

The Problem is, that we have customers, that want that typing in JSX-Files, without using the react wrapped components.

Maybe, as a recommendation, you could consider providing custom manifest elements for JSX typings.
The links below can help you out 🙂 :

@christian-bromann
Copy link
Member

The Problem is, that we have customers, that want that typing in JSX-Files, without using the react wrapped components.

@BenjaminBrossi You don't need React wrapped components. If your customers use JSX they should use camel cased props, if they write in raw HTML files they must use kebab casing. If they need type support in HTML files they our web-types community project may be useful to them.

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

3 participants