38

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"],
}
7
  • How is your project set up; what's in tsconfig.json? Commented May 28, 2019 at 11:27
  • Try declare function require(name:string); at the top. Typescript doesnt support require by default Commented May 28, 2019 at 11:28
  • @jonrsharpe I've updated my question with the tsconfig Commented May 28, 2019 at 11:31
  • @Deckerz Would I have to do that in every Node file I use require in then? That seems annoying if so. Commented May 28, 2019 at 11:38
  • npm i @types/express... for typescript definition. it should fix "Cannot find namespace 'express'." Commented May 28, 2019 at 12:30

5 Answers 5

96

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.

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

1 Comment

I was ready to pull out my hair
18

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.

Comments

2

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

Comments

1

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

Comments

-1

Maybe you have to use import instead of require:

import * as express from 'express';

2 Comments

OP already wrote in his question, that this would fix the error, but no longer is valid Node code, therefore another error gets thrown.
This causes a Typescript error on express() of Cannot invoke an expression whose type lacks a call signature. Type 'typeof e' has no compatible call signatures and also when I try to run the code, since import isn't valid NodeJS code it wouldn't work anyway.

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.