Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: Class extends value undefined is not a constructor or null

This problem has been causing me to lose my sanity for the last couple of days.

Here is my directory structure:

[src]
|- cmds/
|  |- Gh.js
|  \- Help.js
|- commands.js
|...

I am trying to import a class exported by commands.js into Help.js and Gh.js (and any other files I might add in the future). However, I keep getting an error:

class Gh extends _commands.Command {
                           ^
TypeError: Class extends value undefined is not a constructor or null

All of the files are being transpiled using Babel, with env set to "node": "current" and using the wildcard package. I have tried to set it for "browser" to see if it was an issue of it being too "advanced", but I got a different error about super functions (or something), which I assume is the same issue.

Here is the class being exported from commands.js:

export class Command {
  constructor (msg) {
    this.id = msg.author.id
    this.msg = msg
  }
  action () {}
  get data () {
    return readData().user[this.id]
  }
  updateUserData (key, val) {
    updateUserData(this.id, key, val)
  }
  sendMsg (data) {
    sendMsg(this.msg, data)
  } 
}

...and here is cmds/Gh.js, one of the files that I am trying to import Command into:

import {Command} from '../commands'

export class Gh extends Command {
  constructor (msg) {
    super(msg)
    this.desc = 'Returns GitHub repository link and exits'
  }
  action () {
    this.sendMsg('GitHub link: https://github.com/owm111/knife-wife')
  }
}

I tried putting Command into both of the cmds/, and they worked perfectly. However, when moving it back into commands.js, it broke again. I tried changing the path it is importing from from ../commands to ./../commands, ../commands.js, ./../commands.js; none worked. I moving commands.js into cmds/, still broke. I tried to console.log(Command) in both of the cmds/, but they both returned undefined.

All of this makes it look like is a problem with importing, but I cannot figure out what for the life of me. Please help.

like image 803
Owen McGrath Avatar asked Feb 04 '18 00:02

Owen McGrath


1 Answers

If anyone else sees this error, the first thing to look for is circular dependencies. Import file A into B, B into some other file C, and so on. If any of C through Z is imported into A, then JS will not be able to ensure that a file is defined at the time that another file needs it (and will not try to go back and fill in the blanks later).

This was likely the case here, since there was clearly other code not posted, and it only appeared when file dependencies were introduced. The problem exists regardless of file structure: the only structure guaranteed to avoid it is a single giant JS file. The solution is to ensure a strict tree structure of relationships between classes, and use factory methods or alternative communications like emitters to keep the couplings loose.

If you have more than a couple import / require statements, I recommend periodically running a checker like Madge to find and optionally visualize any loops before they become hard to undo.

npm install --save-dev madge
node_modules/madge/bin/cli.js --warning --circular --extensions js ./
like image 164
MBer Avatar answered Nov 07 '22 06:11

MBer