pastorgluk
pastorgluk

Reputation: 321

Use custom TypeScript typing .d.ts in nextjs (Module not found: Can't resolve ...)

I'm using JS library which does not provide @type definition for TypeScript, so I created my own .d.ts file. Let's call it foo.d.ts. My project structure looks like this:

...
.next/
pages/
...
typings/
    foo.d.ts
...
tsconfig.json

My VS Code has no problem with that definition and I can do import in my component, like:

import {Foo} from "foo";

But in run time I get this error in the browser console

Module not found: Can't resolve 'foo'

I have tried to add

"typeRoots": [ "node_modules/@types", "typings" ]

to my tsconfig.json but it didn't help. I've also tried to explicitly add foo.d.ts to the include section where next-env.d.ts is added.

foo.d.ts looks like this:

declare module 'foo' {
    declare interface ValidationError {
        message?: string;
    }
    declare namespace Foo {
        class Bar {
            constructor(config: any, displayErrorsCallback: (data: ValidationError[]) => void, onSubmitTriggered: () => void);
        }
    }
}

Update (added tsconfig)

{
  "compilerOptions": {
    "target": "es6",
    "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",
    "typeRoots": [
      "node_modules/@types",
      "typings"
    ]
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

Upvotes: 12

Views: 17851

Answers (2)

Vadorequest
Vadorequest

Reputation: 17999

With NextJS 14, I ran into this issue today.

Eventually, I had to specify typeRoots this way (it wasn't specified before, and was using some default I'm not aware of):

"typeRoots": [
  "@typings",
  "node_modules",
  "node_modules/@types"
],

The explanation (if I'm being correct):

  • @typings is my own folder for external types (only contains d.ts files)
  • node_modules might contain d.ts types, as some packages release those alongside their sources (this is what I was missing and was breaking next build)
  • node_modules/@types is where modules are releasing their typings (best practice, but not always followed)

The full tsconfig.json file:

{
  "$schema": "https://json.schemastore.org/tsconfig",
  "display": "Next.js",
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "incremental": true,
    "baseUrl": ".",
    "types": [
      "node",
      "jest",
      "@testing-library/jest-dom"
    ],
    "typeRoots": [
      "@typings",
      "node_modules",
      "node_modules/@types"
    ],
    "plugins": [
      {
        "name": "next"
      }
    ]
  },
  "include": [
    "next-env.d.ts",
    "**/*.ts",
    "**/*.tsx",
    "**/*.mjs",
    "jest.config.js",
    ".next/types/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

Upvotes: 1

Slobodan Djordjevic
Slobodan Djordjevic

Reputation: 69

Just add .d after the file name, so import your type definition as import {Foo} from "foo.d"; Whenever importing *.d.ts, import them like that, no need to edit configs.

Upvotes: 5

Related Questions