Typescript: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.ts(7009)

懵懂的女人 提交于 2020-12-03 07:27:51

问题


The following is the code that works best for displaying custom errors in Chrome Devtools, Node.js, etc. Based on this StackOverflow answer.

function CustomErr (message) {
  var err = new Error(message)
  Object.setPrototypeOf(err, CustomErr.prototype)
  return err
}

CustomErr.prototype = Object.create(Error.prototype, {
  name: { value: 'Custom Error', enumerable: false }
})

However, when I convert it to Typescript:

function CustomErr (message: string) {
  var err = new Error(message)
  Object.setPrototypeOf(err, CustomErr.prototype)
  return err
}

CustomErr.prototype = Object.create(Error.prototype, {
  name: { value: 'Custom Error', enumerable: false }
})

Calling throw new CustomErr("something went wrong") shows this error:

'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.ts(7009)

What can I do to correctly type-annotate my code? If you can find another equivalent code solution, feel free to suggest it, but it MUST have the same behavior in Chrome DevTools (this alone of all solutions I tried displays a custom error name nicely). Thanks!

EDIT: Need to support older browsers, so I can't use ES6 classes. I'd prefer not to transpile classes to ES6 because I'm creating a lightweight library, and a class polyfill alone is 10% of my entire codesize.

So to recap, how can I annotate the code I have now?


回答1:


You can declare class, but implement it with a function. This way output (the resulting javascript) won't be affected, but typescript will treat the CustomErr as a "newable":

declare class CustomErr extends Error {
    constructor(message: string);
}

function CustomErr(message: string) {
    var err = new Error(message)
    Object.setPrototypeOf(err, CustomErr.prototype)
    return err
}

CustomErr.prototype = Object.create(Error.prototype, {
    name: { value: 'Custom Error', enumerable: false }
})

throw new CustomErr("something went wrong") // no error now

Playground




回答2:


Few things. What is the purpose of doing code like this, why not let typescript to compile the code down to es5, or Babel. I literally just copy and pasted yow code in here and it compiles: https://codepen.io/jaraolveda/pen/ExaWbxy Which tells me that you are going a lil bit too heavy on the tsconfig.json. But if you really want me o see how to do something like that. Here is an example of how to do it How to implement a Typescript interface to an es5-style "class"?




回答3:


I still have no idea how to annotate my code, but just changing throw new CustomErr('err') to throw CustomErr('err') fixed my problem. Though JS allows you to use the new constructor, TypeScript doesn't.




回答4:


I was able to implement custom errors in TypeScript by doing

interface Exception {
    code: number;
    message: string;
}

export const Exception = (function (this: Exception, code: number, message: string) {
    this.code = code;
    this.message = message;
} as unknown) as { new (code: number, message: string): Exception };

Then I can use it anywhere in my codebase like

throw new Exception(403, 'A custom error');

Or in an async operation

export const CreateUser = async ({ email, password }: { email: string; password: string }): Promise<IUser> => {
    try {
        // some async operations

        throw new Exception(403, 'Error creating user');
    } catch (error) {
        return Promise.reject(error);
    }
};



来源:https://stackoverflow.com/questions/59420203/typescript-new-expression-whose-target-lacks-a-construct-signature-implicit

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!