Andry
Andry

Reputation: 16875

Typescript cannot find type in definition file in node_modules folder

I have a project which has this structure:

project/
├── package.config
├── node_modules/
│   ├── interactjs/
│   ├── ├── index.d.ts
├── src/
│   ├── browser/
│   |   ├── tsconfig.json
│   |   ├── index.ts

I have the following ./package.json:

{
    ...
    "dependencies": {
        "interactjs": "1.3.4"
    },
    "devDependencies": {
        "typescript": "3.2.2"
    }
}

My ./src/browser/tsconfig.json is:

{
    "compilerOptions": {
        "target": "es5",
        "module": "none",
        "declaration": true,
        "strict": true,
        "strictNullChecks": false,
        "outDir": "./out"
    },
    "typeRoots": [
        "../../node_modules",
        "../../node_modules/@types",
        "../definitions"
    ],
    "include": [
        "./**/*"
    ]
}

As you can see I am including also folder definitions as there are some manual definitions I want to include in all Typescript files of my project.

Problem

The following fails compilation:

const p : interact.Position = { x: 1, y: 2 };

With error:

index.ts:9:11 - error TS2503: Cannot find namespace 'interact'.

9 const s : interact.Position = { x: 1, y: 2 };
            ~~~~~~~~

interact is not found even though in node_modules/interactjs file index.d.ts is present with all the definitions.

What is the problem?

Upvotes: 7

Views: 24956

Answers (4)

Ben L
Ben L

Reputation: 744

It looks like you're missing the line "moduleResolution":"node", in your tsconfig.json.

This is what one of my tsconfig.json files looks like.

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "module": "es2015",
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "target": "es5",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2017",
      "dom"
    ]
  }
}

Upvotes: 3

Martijn Dirkse
Martijn Dirkse

Reputation: 677

I fixed a similar problem by creating .yarnrc.yml at the yarn project root (not necessarily the git checkout directory because the yarn root can be a subdirectory in the git project). I filled it as follows:

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.1.1.cjs

This caused yarn to create directory node_modules at the yarn project root instead of somewhere else. Now VSCode can find the types.

I did so based on: Yarn v3.0.2 Why do not install the node_modules folder ? Need to run npm install after the yarn's commands?

Upvotes: -2

Mark Coleman
Mark Coleman

Reputation: 40863

If you wish to keep module resolution to none adding the typing file into the "include" section should give you the output desired.

tsconfig.json

{
    "compilerOptions": {
        "target": "es5",
        "module": "none",
        "declaration": true,
        "strict": true,
        "strictNullChecks": false,
        "outDir": "./out",
        "noImplicitAny": false //<------ to ignore the errors in interactjs/index.d.ts
    },
    "typeRoots": [
        "../../node_modules",
        "../../node_modules/@types",
        "../definitions"
    ],
    "include": [
        "../../node_modules/interactjs/index.d.ts", //<----- include interact in the global scope
        "./**/*"
    ]
}

index.ts

const p : interact.Position = { x: 1, y: 2 };
const s : interact.SnapPosition = { x: 1, y: 2, range: 0 };

const listener : interact.Listener = (e: interact.InteractEvent)=>{
    console.log(e);
};

interact.on("cancel", listener)

built index.js

"use strict";
var p = { x: 1, y: 2 };
var s = { x: 1, y: 2, range: 0 };
var listener = function (e) {
    console.log(e);
};
interact.on("cancel", listener);

Upvotes: 6

Jesse Hallett
Jesse Hallett

Reputation: 2017

When you import a package Typescript (and Node) determine which file/module to import from that package by looking for a main field in the package.json file included with the package. The package.json file in interactjs includes this line:

"main": "dist/interact.js",

That means that the main module in the interactjs package is named interact.js, and it is in the dist/ directory.

If the package.json file of the package does not explicitly specify the location of a type definition file, Typescript will assume that the type definition file has the same base name and location as the package's main module. Given the location of the main module in interactjs, Typescript will look for type definitions in the file dist/interact.d.ts. Try renaming the type definition file from index.d.ts to interact.d.ts, and make sure that it is in the dist/ directory.

If you are authoring a package that includes Typescript definitions it is helpful to make the location of the definition file explicit by including a types field in your package.json field as is described in the publishing guide

Upvotes: 5

Related Questions