13

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"
  ]
}
7
  • Have you actually installed foo? .d.ts files just declare types and assume the package is present, you still have to npm install the package itself. Commented Mar 24, 2021 at 19:07
  • I’m importing foo.js with <script .../> so in runtime it works. Commented Mar 24, 2021 at 19:35
  • In my d.ts file I declare module “foo”, I thought that means that I have to use import “foo”? Commented Mar 24, 2021 at 19:36
  • @pastorgluk You're correct, I missed that part when I first read the question. Could you add your tsconfig.json please? Commented Mar 25, 2021 at 1:16
  • sure, added tsconfig to the question Commented Mar 25, 2021 at 11:21

2 Answers 2

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

This works, but is this the way it's supposed to work? It seems like it's just treating the .d.ts file as a regular typescript file, so isn't this the same as just renaming the file from foo.d.ts to just foo.ts?
also curious about this (now that Next.js in v14+). No official documentation discusses best practices on this as yet.
1

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"
  ]
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.