The problem
When using TypeScript with JSX, attempting to use a Pharos web component without extending the JSX namespace will result in an error like the following:
Property my-app-pharos-button does not exist on type JSX.IntrinsicElements
To resolve this you must extend the JSX namespace to let the compiler know it's an allowable element:
declare module "react" {
namespace JSX {
interface IntrinsicElements {
"my-app-pharos-button": { [key: string]: any } & React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>
}
}
}
The example above allows any HTML attribute with any value, while still retaining strongly typed built-in React DOM props like (onClick, className, etc.).
While this works, it's annoying because
- Since
any attribute is allowed with any value, there isn't strong type safety and therefore leads to a lack of IntelliSense.
- Each time I want to use a new Pharos component I have to remember to add it to the list. This list is not be confused with the other required list necessary to register Pharos components at runtime (ie.
registerComponents). Not as bad as the first problem, but can be annoying.
The frequency of this friction will increase over time as more teams upgrade to React 19 and opt to use native web components instead of React wrappers, now that React 19 offers native support for them.
The solution
One possible solution is to enhance Pharos to provide TypeScript types that accurately represent the HTML elements and their attributes, allowing consumers to include them in their projects when using these elements in JSX.
Something like:
import type { PharosButtonElement } from "@ithaka/pharos";
declare module "react" {
namespace JSX {
interface IntrinsicElements {
"my-app-pharos-button": PharosButtonElement,
...
}
}
}
Keep in mind - since we are dealing with HTML the properties need to be kebab-case instead of camelCase.
Additional information
- Pharos is currently using React 18. Might be worth discussing the future of the React wrappers once we upgrade to React v19.
The problem
When using TypeScript with JSX, attempting to use a Pharos web component without extending the JSX namespace will result in an error like the following:
To resolve this you must extend the JSX namespace to let the compiler know it's an allowable element:
The example above allows
anyHTML attribute withanyvalue, while still retaining strongly typed built-in React DOM props like (onClick, className, etc.).While this works, it's annoying because
anyattribute is allowed withanyvalue, there isn't strong type safety and therefore leads to a lack of IntelliSense.registerComponents). Not as bad as the first problem, but can be annoying.The frequency of this friction will increase over time as more teams upgrade to React 19 and opt to use native web components instead of React wrappers, now that React 19 offers native support for them.
The solution
One possible solution is to enhance Pharos to provide TypeScript types that accurately represent the HTML elements and their attributes, allowing consumers to include them in their projects when using these elements in JSX.
Something like:
Keep in mind - since we are dealing with HTML the properties need to be kebab-case instead of camelCase.
Additional information