CaribouCode
CaribouCode

Reputation: 14398

Typescript: Cannot find namespace

I have the following simple NodeJS code:

const express = require('express');

const server: express.Application = express();

I'm adding Typescript to my project and am new to it so forgive me. With the above code I get the following issues/errors:

For the require:

var require: NodeRequire (id: string) => any (+1 overload)
'require' call may be converted to an import.

For the express.Application usage:

Cannot find namespace 'express'.

If I switch the 'require' to 'import' it fixes the namespace error but is no longer valid Node code so doesn't run (throws a new error about unexpected token for the import).

What's the correct way to write Node code like this with Typescript to avoid these errors?

My tsconfig.json looks like this:

{
  "compilerOptions": {
    "allowJs": true,
    "allowSyntheticDefaultImports": true,
    "alwaysStrict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "jsx": "preserve",
    "lib": ["dom", "es2017"],
    "module": "esnext",
    "moduleResolution": "node",
    "noEmit": true,
    "noFallthroughCasesInSwitch": true,
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "removeComments": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "strict": true,
    "target": "esnext",
  },
  "exclude": ["node_modules"],
}

Upvotes: 35

Views: 69695

Answers (5)

nonNumericalFloat
nonNumericalFloat

Reputation: 1767

tsConfig compilerOptions "types"

For me it was the compilerOptions -> types that contained a type, in this case "googlemaps" instead of "google.maps" for namespace declaration.

{
  "compilerOptions": {
    "types": [
       ...
      "google.maps"
       ...
    ],
  }
}

From the docs:

If types is specified, only packages listed will be included in the global scope

Upvotes: 1

Anjan Talatam
Anjan Talatam

Reputation: 3996

Use enum instead of object

My code satisfies all the answers mentioned above. "module": "commonjs" and my file is already a .tsx file.

Still getting this error. Here is how I got this error.

In my payload, I have a key(shape) based on which some other details of the payload are dependent.

export const SHAPES = {
  SQUARE: "square",
  CIRCLE: "circle",
};

Note: I am using this SHAPES object to store constants

If you are trying to use the value of an object as a type for an interface then you will get this error.

interface ICirclePayload {
  shape: SHAPES.CIRCLE;
  details: {
    radius: number;
  };
}

interface ISquarePayload {
  shape: SHAPES.SQUARE;
  details: {
    length: number;
  };
}

You will get the below error for SHAPES in both the interfaces

Cannot find namespace 'SHAPES'.ts(2503)

SOLUTION FROM HERE

Change object to enum

export const enum SHAPES {
  SQUARE = "square",
  CIRCLE = "circle",
}

With the above code, the error should be resolved.

Consider reading What is the difference between enum and object in typescript

Upvotes: 2

a2f0
a2f0

Reputation: 1835

In case you are a React dev that ends up here as I did - if there is JSX syntax in the file, try changing the extension of the file from .ts to .tsx.

Upvotes: 89

CaribouCode
CaribouCode

Reputation: 14398

After a lot of wasted time, it turns out this was due to the module setting in the tsconfig file which should be:

"module": "commonjs"

This means Typescript will output common js modules instead of ES6 modules, meaning the code will run correctly as NodeJS code. I was therefore able to change require to import, since it compiles.

Upvotes: 17

Darwin Gonzalez
Darwin Gonzalez

Reputation: 173

Maybe you have to use import instead of require:

import * as express from 'express';

Upvotes: -1

Related Questions