Home > Back-end >  "Module not found" when extending a class
"Module not found" when extending a class

Time:10-22

Every time when I try to extend the abtract class Command and I try to compile I get the error: Error: Cannot find module 'src/classes/commandBase'

My project has the following structure:

   ├────tsconfig.json
   └────src
        ├───classes
        │   └───commandBase.ts
        ├───commands
        │   └───ping.ts
        ├───handlers
        ├───listeners
        └───models

commandBase.ts

abstract class Command {
  name: string;
  abstract execute(client: Client, message: Message, args: string[]): void;

  constructor(name: string) {
    this.name = name;
  }
}
export default Command;

ping.ts

import Command from "src/classes/commandBase";

class Ping extends Command {
  constructor() {
    super("ping");
  }
  async execute(
    client: Client,
    message: Message,
    args: string[]
  ): Promise<void> {
    // ...
  }
}

export default Ping;

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "CommonJS",
    "rootDir": "./src/",
    "outDir": "./dist/",
    "strict": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "allowSyntheticDefaultImports": true,
    "resolveJsonModule": true,
    "forceConsistentCasingInFileNames": true,
    "removeComments": true,
    "typeRoots": ["node_modules/@types"],
    "sourceMap": true,
    "baseUrl": ".",
    "paths": {}
  },
  "include": ["./**/**/*.ts"],
  "exclude": ["node_modules", "dist"]
}

However

If I change import Command from "src/classes/commandBase"; to import Command from "../classes/commandBase"; everything is working fine, no errors appear. The thing is I use autocompletion (VS Code) and everytime I import "Command" it automatically writes "src/classes/commandBase";

Another thing is if I create a new file which doesnt extend Command but imports it everything is also working as intended. So I am very confused about this behavior.

File foo.ts

import Command from "src/classes/commandBase";

const foo: Command = {
  name: "",
  execute: function (client: Client, message: Message, args: string[]): void {
    throw new Error("Function not implemented.");
  }
}

CodePudding user response:

Set typescript.preferences.importModuleSpecifier to relative in your settings (JSON):

"typescript.preferences.importModuleSpecifier": "relative"

It doesn't error in foo.ts because Command is being used as a type and not as a class to extend from. Types are erased at runtime, so there is no error because the import has been erased.

CodePudding user response:

That is because your Classes and Commands folders are in the src directory, you don't need to leave that directory. Your path should be something like ./classes/ or ./commands/Ping if you're running from the main folder.

../ indicates that you're leaving the current directory to go up one ./ is in the current directory

Here is not specifying "./" before source folder

This configuration run to me, check structure and configuration are you using about module in tsconfig.json, and choice 'absolute paths' instead to avoid relative path cases as "../../../", if not specify in your VSCode settings.json "typescript.preferences.importModuleSpecifier": "relative",

import Command from "@classes/commandBase";

tsconfig.json

/* Modules */
    "module": "commonjs",
    "rootDir": "./src",
    "baseUrl": ".",
    "paths": { /* Set absolute paths with '@path' */
      "@config/*": ["./src/config/*"],
      "@controllers/*": ["./src/controllers/*"],
      "@services/*": ["./src/services/*"],
      "@classes/*": ["./src/classes/*"],
      "@commands/*": ["./src/commands/*"],
      "@routes/*": ["./src/routes/*"],
      "@pages/*": ["./src/pages/*"],
      "@utils/*": ["./src/utils/*"],
      "@middlewares/*": ["./src/middlewares/*"]
    }

    // Allow multiple folders to be treated when resolving modules
    "typeRoots": [
      "./node_modules/@types",
      "./src/@types"

package.json

    "plugins": [
      [
        "module-resolver",
        {
          "alias": {
            "@config": "./src/config",
            "@controllers": "./src/controllers",
            "@services": "./src/services",
            "@classes": "./src/classes",
            "@commands": "./src/commands",
            "@routes": "./src/routes",
            "@pages": "./src/pages",
            "@utils": "./src/utils",
            "@middlewares": "./src/middlewares"
          }
        }
      ]
    ]
  }
}

Recomendations:

  • Check this VSCode settings.json
  • Add the following tags in your StackOverflow Question to better help!

#nodejs #module #relative-path #import

  • Related