Wilker
Wilker

Reputation: 651

Typescript show error for .mdx extension file in nextjs

It work fine for render component to website but typescript show error for import mdx file.

typescript error message: Cannot find module '@/articles/good.mdx' or its corresponding type declarations.

I found a ton of comment in stack overflow. But it still don't solve this issue. Tried installed @mdx-js/mdx, same not work.

import React from "react";

import Layout from "@/components/Layout/index";
import Good from "@/articles/good.mdx"; // this line show typescript error

const index = () => {
  return (
    <Layout>
      <Good />
    </Layout>
  );
};

export default index;

Package.json (removed some unrelated)

{
  "dependencies": {
    "@next/mdx": "^10.2.0",
    "@types/react-transition-group": "^4.4.1",
    "next": "10.1.3",
    "next-seo": "^4.24.0",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-query": "^3.13.11",
    "react-transition-group": "^4.4.1"
  },
  "devDependencies": {
    "@mdx-js/loader": "^1.6.22",
    "@types/node": "^15.0.1",
    "@types/react": "^17.0.4",
    "@types/webpack-env": "^1.16.0",
    "autoprefixer": "^10.2.5",
    "typescript": "^4.2.4"
  }
}

tsconfig.json (removed some unrelated)

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "types": [
      "node",
      "webpack-env"
     ]
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "**/*.mdx",
  ],
  "exclude": [
    "node_modules"
  ]
}

Upvotes: 6

Views: 7966

Answers (3)

enoch
enoch

Reputation: 3123

To resolve this, create a file called mdx.d.ts and place it either in the root or the types folder in the root of your project and paste the following code:

declare module '*.mdx' {
  let MDXComponent: (props: any) => JSX.Element;
  export default MDXComponent;
}

This defines the global types for .mdx files and tells typescript that default imports from .mdx files return (props: any) => JSX.Element, which makes it safe to use in your .tsx files as <YourMdxComponent />.

Upvotes: 14

ALFmachine
ALFmachine

Reputation: 808

mdxjs now supports types

npm install @types/mdx --save-dev

Upvotes: 16

konstantin555
konstantin555

Reputation: 132

More convinient way is to install types yarn add @types/mdx. Then just include those types in your tsconfig.ts

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "types": [
      "node",
      "webpack-env", 
      "mdx"
     ]
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "**/*.mdx",
  ],
  "exclude": [
    "node_modules"
  ]
}

You will still get type errors if you want to reexport a custom component from mdx file like

import YourMdxContent, { SomeComponent } from './YourMdxFile.mdx'

You will get an error:

Module '"*.mdx"' has no exported member 'SomeComponent'. Did you mean to use 'import SomeComponent from "*.mdx"' instead?

If this happens you will need to redeclare mdx module:

declare module '*.mdx' {
  export function SomeComponent(): JSX.Element;
}

No need to redeclare MDXContent as it is already inherited from types.

Upvotes: 9

Related Questions