admin管理员组

文章数量:1327524

I am trying to call the function of the parent class from the child but the keyword super is throwing and error. I am using typescript, here is a snippet of the package.json from the project.

{
  "scripts": {
    "build": "tsc",
    "start": "nodemon",
    "prod": "npm run build && npm run start"
  },
  "dependencies": {
    "body-parser": "^1.18.3",
    "dotenv": "^6.1.0",
    "express": "^4.16.4"
  },
  "devDependencies": {
    "@types/body-parser": "^1.17.0",
    "@types/dotenv": "^4.0.3",
    "@types/express": "^4.16.0",
    "@types/node": "^10.12.2",
    "nodemon": "^1.18.5",
    "ts-node": "^7.0.1",
    "tslint": "^5.11.0",
    "typescript": "^3.1.6"
  }
}

The parent class

export default class baseController {

  public response = (message = "", status = 200) => (
    req: Request,
    res: Response
  ) => {
    return res.status(status).send({
      status: true, // true if success, false if faliure
      message: message, // message to display incase of error
      payload: []
    });
  };
}

The child class

import BaseController from "../baseController";

export default class UsersController extends BaseController {

  constructor() {
    super();
  }

  public fetchUsers = async () => {
    return super.response("testing");
  };
}

The code crashes on the line return super.response("testing"); with the error super keyword unexpected here.

Here is my tsconfig.json

{
  "pilerOptions": {
    "module": "monjs",
    "esModuleInterop": true,
    "target": "es6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "./dist",
    "pretty": true,
    "baseUrl": "./src",
    "alwaysStrict": true,
    "paths": {
      "*": ["node_modules/*", "src/types/*"]
    }
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}

I am trying to call the function of the parent class from the child but the keyword super is throwing and error. I am using typescript, here is a snippet of the package.json from the project.

{
  "scripts": {
    "build": "tsc",
    "start": "nodemon",
    "prod": "npm run build && npm run start"
  },
  "dependencies": {
    "body-parser": "^1.18.3",
    "dotenv": "^6.1.0",
    "express": "^4.16.4"
  },
  "devDependencies": {
    "@types/body-parser": "^1.17.0",
    "@types/dotenv": "^4.0.3",
    "@types/express": "^4.16.0",
    "@types/node": "^10.12.2",
    "nodemon": "^1.18.5",
    "ts-node": "^7.0.1",
    "tslint": "^5.11.0",
    "typescript": "^3.1.6"
  }
}

The parent class

export default class baseController {

  public response = (message = "", status = 200) => (
    req: Request,
    res: Response
  ) => {
    return res.status(status).send({
      status: true, // true if success, false if faliure
      message: message, // message to display incase of error
      payload: []
    });
  };
}

The child class

import BaseController from "../baseController";

export default class UsersController extends BaseController {

  constructor() {
    super();
  }

  public fetchUsers = async () => {
    return super.response("testing");
  };
}

The code crashes on the line return super.response("testing"); with the error super keyword unexpected here.

Here is my tsconfig.json

{
  "pilerOptions": {
    "module": "monjs",
    "esModuleInterop": true,
    "target": "es6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "./dist",
    "pretty": true,
    "baseUrl": "./src",
    "alwaysStrict": true,
    "paths": {
      "*": ["node_modules/*", "src/types/*"]
    }
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"]
}
Share Improve this question edited Nov 4, 2018 at 12:12 Jude Fernandes asked Nov 4, 2018 at 11:59 Jude FernandesJude Fernandes 7,51712 gold badges54 silver badges92 bronze badges 5
  • 1 Did you notice that BaseController is once lowercased and once uppercased? – Christian Vincenzo Traina Commented Nov 4, 2018 at 12:01
  • @CristianTraìna added the missing import statement for the base controller and tried it with all same case, still getting the issue. – Jude Fernandes Commented Nov 4, 2018 at 12:13
  • 1 I'm not so familiar with TypeScript, but with regular JS you need to have a constructor in the base class in order to call super() in the child class – Jacob Commented Nov 4, 2018 at 12:25
  • @Jacob tried that too, didn't work – Jude Fernandes Commented Nov 4, 2018 at 12:26
  • Try creating the functions like this: public async fetchUsers() {} instead of assigning it to a variable with all your functions – Jacob Commented Nov 4, 2018 at 12:31
Add a ment  | 

2 Answers 2

Reset to default 7

This case is one of several reasons why prototype methods may be preferred over arrow class fields (instance methods), as explained in this answer.

There are several problems here.

One problem is that there's no super.response. super refers to parent class prototype, while response is instance method.

Another problem is that the target is ES6. async is transpiled to generators, and super is not transpiled, this results in incorrect code:

fetchUsers.a = () => __awaiter(this, void 0, void 0, function* () { return super.response("testing") });

Only arrow functions can get super from parent scope, super is not allowed inside non-arrow functions. Since there are no arrow generators, super use is invalid inside a generator. While TypeScript is able to handle super properly in async prototype methods:

fetchUsers() {
    const _super = name => super[name];
    return __awaiter(this, void 0, void 0, function* () { _super.response("testing").call(this); });
}

Yet another problem is that referring to super in a class that doesn't override response is semantic mistake. Child class already inherits response. It can be used as this method.

It should be:

export default class baseController {
  public response(message = "", status = 200) (...) { ... }
}

export default class UsersController extends BaseController {
  public async fetchUsers() {
    return this.response("testing");
  };
}

If fetchUsers is expected to be used as a callback (this is the only good use for arrow methods), it should be bound to this context in constructor:

  public fetchUsers = this.fetchUsers.bind(this);

  public async fetchUsers() {
    return this.response("testing");
  };

Where fetchUsers class field is sugar syntax for constructor body.

Your problem is with how you're creating the class's functions. It should be like this:

export class baseController {

    public response(message = "", status = 200) { 

    }
}


export class UsersController extends baseController {

  constructor() {
    super();
  }

  public async fetchUsers() {
    return super.response("testing");
  };
}

本文标签: javascriptUnable to use super to call inherited class functionStack Overflow