Let’s say I have a custom element setapp-badge
that I want to use in my tsx files. If I go ahead and use it, the compiler will throw an error and Next.js will fail to build. It seems the problem might be a combination of how Next.js, TypeScript, and custom elements work together. Therefore, let’s try an approach that avoids the namespace/module issues while ensuring custom elements are recognized in a Next.js/TypeScript project.
Using @types/react
Augmentation and Ensuring Proper Recognition of Custom Elements
Instead of extending JSX.IntrinsicElements
or HTMLElementTagNameMap
, we will focus on properly extending the React
types for custom elements directly in a way that Next.js can handle.
Step 1: Ensure TypeScript Knows the Custom Element
Place the following in a file, say custom-elements.d.ts
in the root or src/types/
:
// custom-elements.d.ts
declare namespace JSX {
interface IntrinsicElements {
'setapp-badge': {
appId: string;
vendorId: string;
theme: string;
};
}
}
Why this should work
- Declaring
IntrinsicElements
within theJSX
namespace directly ensures Next.js and TypeScript treatsetapp-badge
as a valid intrinsic element. - No use of
declare module
ornamespace
: We avoid augmenting the React module itself, which seems to be the root of the issue.
Step 2: Verify tsconfig.json
Includes the Declarations
Ensure your tsconfig.json
file includes the declaration file:
{
"compilerOptions": {
// other options
},
"include": [
"custom-elements.d.ts",
"src/**/*"
]
}
Step 3: Use setapp-badge
in Your JSX
Now you can use your custom element in any .tsx
file like this:
<setapp-badge appId="401" vendorId="285" theme="dark"></setapp-badge>
Key Benefits
- Avoids ESLint Issues: This solution does not trigger the
@typescript-eslint/no-namespace
rule since we’re not usingnamespace
ordeclare module
. - Simple IntrinsicElements Extension: We’re directly extending
JSX.IntrinsicElements
, which is allowed in TypeScript and recognized by Next.js. - Next.js Friendly: No need for advanced or experimental TypeScript configurations.
This approach avoids the problems we’ve encountered before and directly adds the custom element to JSX without creating issues with Next.js.
Why other solutions might fail
declare module
/namespace
: Next.js might not handle these well in TypeScript configurations, leading to the errors.- Next.js JSX handling: By extending
JSX.IntrinsicElements
directly within adeclare namespace JSX
, we avoid Next.js misinterpreting the custom element.