TypeScript cannot find module if it contains a require

1.4k Views Asked by At

I'm trying to understand how to properly work with TypeScript and classic JS node modules.

I set up a very basic project, with the following file architecture:

.
├── index.ts
├── lodash.d.ts
├── module.ts
└── node_modules
    └── lodash

lodash has been installed with npm. As it seems to provide no typings info, I wrote a basic d.ts file that only describes one function, just to please tsc and avoid error about not knowing lodash.

lodash.d.ts

declare module "lodash" {
  export function reverse(array: any[]): any[];
}

In my module.ts file, I import lodash with require and expose a function on a module, which I use on index.ts file.

module.ts

/// <reference path="./lodash.d.ts" />

import _ = require('lodash');

module FooModule {
  export function foo() {
    return _.reverse([1, 2, 3]);
  }
}

index.ts

/// <reference path="./module.ts" />

let a = FooModule.foo();
console.log(a);

The problem is that tsc (and so VS Code) tells me that it can't find name FooModule.

$ tsc index.ts --module commonjs -outDir build
index.ts(3,9): error TS2304: Cannot find name 'FooModule'.

However, if I remove the import _ = require('lodash'); from module.ts, it works correctly (except the obvious fact that _ variable is now undefined).

Am I doing something wrong with this require?

1

There are 1 best solutions below

3
On BEST ANSWER

You are mixing internal modules and external modules. If you use a top-level import or export statement in a .ts file, the file itself is automatically considered as an external module, its contents all part of that module (require is an import statement).

If you put an internal module inside an external module (module or namespace keyword), you are effectively double-wrapping your module contents. That is not good.

Take the following example:

module.ts

import _ = require('lodash');

module FooModule {
    export function foo() {
        return _.reverse([1, 2, 3]);
    }
}

Function foo is now effectively module.FooModule.foo if you export the internal module FooModule from external module module:

export module FooModule {
    // ...
}

However, this is bad.