Types of property 'pre' are incompatible when using inside MDXComponents for generating RSS feed #1940
-
I am trying to generate RSS feed using MDX. I have a bunch of custom MDX components: import React from 'react'
import { getMDXComponent } from 'mdx-bundler/client'
import { Img } from '@/components/mdx/Img'
import { Pre } from '@/components/mdx/Pre'
import { TOC } from '@/components/mdx/TOC'
import { Sidenote } from '@/components/mdx/Sidenote'
export const MDXComponents = {
pre: Pre,
Img,
TOC,
Sidenote,
}
interface IMDXLayoutRenderer {
mdxSource?: any
}
export const MDXLayoutRenderer = ({ mdxSource, ...rest }: IMDXLayoutRenderer): JSX.Element => {
const MDXLayout = React.useMemo(() => getMDXComponent(mdxSource), [mdxSource])
return <MDXLayout components={MDXComponents as any} {...rest} />
} The import React from 'react'
import { CopyToClipboard } from '@/components/index'
interface IPre {
children: React.ReactChild
theme: string
showLineNumbers: boolean
}
export const Pre = ({ children, theme, showLineNumbers, ...props }: IPre) => {
return (
<CopyToClipboard>
<pre
className={`px-4 py-3 overflow-x-auto rounded-lg font-jetbrains ${
theme ? `${theme}-theme` : 'bg-syntaxBg'
} ${showLineNumbers ? 'line-numbers' : ''}`}
>
{children}
</pre>
</CopyToClipboard>
)
} It's usage is like this in my const mdx = (
<MDXProvider components={MDXComponents}>
<MDXLayoutRenderer mdxSource={code} />
</MDXProvider>
) I believe this is due to a mismatch in what The complete error looks like:
How do I solve this? This error is far too common whenever I use a Custom MDX Component. I'm using it with |
Beta Was this translation helpful? Give feedback.
Replies: 9 comments 20 replies
-
The problem is explained in the error message:
You can’t just say that |
Beta Was this translation helpful? Give feedback.
-
only doing const mdx = (
<MDXProvider components={MDXComponents as any}>
<MDXLayoutRenderer mdxSource={code} />
</MDXProvider>
) |
Beta Was this translation helpful? Give feedback.
-
The issue is interface IPre {
children: React.ReactChild
theme: string
showLineNumbers: boolean
}
interface IPre {
children: React.ReactElement;
theme?: string;
showLineNumbers?: boolean;
} Example in sandbox showing that it can be typed without |
Beta Was this translation helpful? Give feedback.
-
I'm having the same problem. I'm using next-mdx-remote with Typescript 5.2.2. If I set strict mode in tsconfig.json following error occurs.
The error disappears if I disable strict mode or set @ts-expect-error directive as following: export default function MDXContent({source}: {source: string}) {
// @ts-expect-error Server Component
return <MDXRemote source={source} components={comps} options={opts} />
} |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot. I've verified deduped @types/react package as following:
and npm packages as following:
Then, how can I resolve the problem? Indeed I'm newbie in Javascript world. The |
Beta Was this translation helpful? Give feedback.
-
Thank you for your reply. I found the problem is caused by Next.js. It seems they ignoring tsconfig.json settings. The error persists on Visual Studio Code even if I changed the settings to $ npm run build
> monzy@0.1.0 build
> next build
▲ Next.js 14.0.1
- Environments: .env
✓ Creating an optimized production build
✓ Compiled successfully
Linting and checking validity of types ..
We detected TypeScript in your project and reconfigured your tsconfig.json file for you. Strict-mode is set to false by default.
The following mandatory changes were made to your tsconfig.json:
- jsx was set to preserve (next.js implements its own optimized jsx transform)
Linting and checking validity of types ..Failed to compile.
./app/components/MDXContent.tsx:32:37
Type error: Type '{ pre: ({ children, ...props }: IPre) => React.ReactElement<any, string | React.JSXElementConstructor<any>>; Button: ({ text }: { text: string; }) => React.JSX.Element; }' is not assignable to type 'Readonly<MDXComponents> | MergeComponents | null | undefined'.
Type '{ pre: ({ children, ...props }: IPre) => React.ReactElement<any, string | React.JSXElementConstructor<any>>; Button: ({ text }: { text: string; }) => React.JSX.Element; }' is not assignable to type 'Readonly<MDXComponents>'.
Types of property 'pre' are incompatible.
Type '({ children, ...props }: IPre) => React.ReactElement<any, string | React.JSXElementConstructor<any>>' is not assignable to type 'Component<DetailedHTMLProps<HTMLAttributes<HTMLPreElement>, HTMLPreElement>> | undefined'.
Type '({ children, ...props }: IPre) => React.ReactElement<any, string | React.JSXElementConstructor<any>>' is not assignable to type '(props: DetailedHTMLProps<HTMLAttributes<HTMLPreElement>, HTMLPreElement>) => ReactNode'.
Types of parameters '__0' and 'props' are incompatible.
Type 'DetailedHTMLProps<HTMLAttributes<HTMLPreElement>, HTMLPreElement>' is not assignable to type 'IPre'.
Types of property 'children' are incompatible.
Type 'ReactNode' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>>'.
Type 'undefined' is not assignable to type 'ReactElement<any, string | JSXElementConstructor<any>>'.
30 | export default function MDXContent({source}: {source: string}) {
31 | // cba@ts-expect-error Server Component
> 32 | return <MDXRemote source={source} components={comps} options={opts} />
| ^
33 | }
34 | |
Beta Was this translation helpful? Give feedback.
-
Sorry again for my inconvenience. I realized my case should be concrete(I have to use CodeBlock component with import { MDXRemote } from '@/app/lib/next-mdx-remote/rsc'
import CodeBlock from './CodeBlock';
interface CodeBlockProps {
children: React.ReactElement;
}
const comps = { pre: CodeBlock };
export default function MDXContent({source}: {source: string}) {
// ignore@ts-expect-error Server Component
return <MDXRemote source={source} components={comps} options={opts} />
} |
Beta Was this translation helpful? Give feedback.
-
I've found type casting can be a workaround. import { MDXComponents } from 'mdx/types';
const comps = { pre: CodeBlock, } as MDXComponents; |
Beta Was this translation helpful? Give feedback.
The issue is
children
of intrinsic elements isReact.ReactElement
notReact.ReactChild
theme
andshowLineNumbers
should also be marked as optional because they may not be passed.Example in sandbox showing that it can be typed without
any
https://codesandbox.io/s/component-typing-example-dvc35?file=/src/App.tsx:73-170