Skip to content

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

Open
@BenjaminBrossi

Description

@BenjaminBrossi

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions