[WICG/webcomponents] TypeScript & Framework Support for Scoped Custom Element Registries (Issue #1118)

maxpatiiuk created an issue (WICG/webcomponents#1118)

Raising a discussion question for the [Scoped Custom Element Registries](https://wicg.github.io/webcomponents/proposals/Scoped-Custom-Element-Registries.html) proposal

How will TypeScript support for this feature look like, both for DOM typing and JSX support?

## DOM typing support

The following APIs in lib.dom.d.ts rely on `keyof HTMLElementTagNameMap`:

```
Document.createElement
Document.getElementsByTagName
Element.closest
Element.getElementsByTagName
Element.querySelector
Element.querySelectorAll
```

Web component libraries usually extent the `HTMLElementTagNameMap` interface to provide types for their elements.
However, the `HTMLElementTagNameMap` is a global interface.

## JSX typing support

In TypeScript, JSX typing works by extending the namespace associated with a given jsx factory function:

```ts
  export namespace h.JSX {
    interface IntrinsicElements {
      "calcite-accordion": CalciteAccordion;
    }
  }
```

However, the `IntrinsicElements` interface assumes that one tag name maps to one type.

---

The above might not be an issue depending on the scope of the proposal.

If I am reading the proposal right, as an example:
- a page may contain different versions of FluentUI because of FluentUI version mismatches between your dependencies, or components registered by browser extensions.

But, a given app is most likely only interested in directly using only one copy of FluentUI - the one that is declared in their package.json. So ideally, `HTMLElementTagNameMap` and `IntrinsicElements` would only include contributions from your FluentUI copy.

But, if the spec includes the use case of a single app using two different tag names with the same tag name, typing gets tricky.

Theoretically, ShadowRoot interface can gain a type parameter that, if not provided, defaults to `HTMLElementTagNameMap`. This will correctly type `shadowRoot.createElement`, though doesn't help with `element.querySelector`.
For JSX, baring changes to how TypeScript does JSX typing, we would need a separate JSX factory for each custom element registry.

Both problems are solvable, but raise DX and complexity concerns

---

The proposal in current form only permits scoped registries inside shadow root. This excludes React, Angular, and Vue from being able to use this feature or being directly impacted by it. Among remaining JSX frameworks, there is Stencil, and Lit-based frameworks that add JSX sugar.
The DOM API typing for scoped elements impacts non-JSX users too.

---

cc @justinfagnani


-- 
Reply to this email directly or view it on GitHub:
https://github.com/WICG/webcomponents/issues/1118
You are receiving this because you are subscribed to this thread.

Message ID: <WICG/webcomponents/issues/1118@github.com>

Received on Thursday, 4 December 2025 03:44:43 UTC