【问题标题】:Typescript: 'new' expression, whose target lacks a construct signature, implicitly has an 'any' type.ts(7009)打字稿:“新”表达式,其目标缺少构造签名,隐式具有“任何”类型.ts(7009)
【发布时间】:2020-04-12 16:04:03
【问题描述】:

以下是最适合在 Chrome Devtools、Node.js 等中显示自定义错误的代码。基于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 }
})

但是,当我将其转换为 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 }
})

调用throw new CustomErr("something went wrong") 显示此错误:

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

如何正确地对我的代码进行类型注释?如果您能找到另一个等效的代码解决方案,请随时提出建议,但它必须在 Chrome DevTools 中具有相同的行为(我尝试过的所有解决方案中都可以很好地显示自定义错误名称)。谢谢!

编辑: 需要支持旧版浏览器,所以不能使用 ES6 类。我不希望将类转换为 ES6,因为我正在创建一个轻量级库,并且仅一个类 polyfill 就占我整个代码大小的 10%。

所以回顾一下,我如何注释我现在拥有的代码?

【问题讨论】:

  • 您是否在编译时收到此错误?
  • 你必须编译(或至少是 trasile)打字稿,不编译是什么意思......没有它你将无法运行打字稿。
  • 如果你确实想要一个轻量级的 ES5 库,你可能真的想考虑编写一个轻量级的 ES5 库,并且在此过程中不要接触 TypeScript。反之亦然:如果你编写 TypeScript,让工具担心 JavaScript。

标签: javascript typescript ecmascript-5


【解决方案1】:

几件事。做这样的代码的目的是什么,为什么不让 typescript 把代码编译成 es5,或者 Babel。 我实际上只是在这里复制并粘贴了你的代码并编译:https://codepen.io/jaraolveda/pen/ExaWbxy 这告诉我你在tsconfig.json 上有点太重了。 但如果你真的想让我看看如何做这样的事情。这是一个如何做到这一点的例子How to implement a Typescript interface to an es5-style "class"?

【讨论】:

    【解决方案2】:

    我仍然不知道如何注释我的代码,但只是将 throw new CustomErr('err') 更改为 throw CustomErr('err') 解决了我的问题。虽然 JS 允许你使用 new 构造函数,但 TypeScript 不允许。

    【讨论】:

    【解决方案3】:

    你可以声明类,但是用一个函数来实现它。这样输出(生成的 javascript)不会受到影响,但 typescript 会将 CustomErr 视为“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

    【讨论】:

    • 如何导出类型和函数? TypeScript 告诉我不允许导出它
    • 您遇到了哪个错误? typescriptlang.org/play?#code/…
    • 嗨@AlekseyL。我使用了您指定的方法,但出现错误。请看stackoverflow.com/questions/64323473/…提前谢谢!
    • 我同意@DavidAlsh - declareintended 在导出具有相同名称的declare classfunction 时定义非TS 外部引用(例如C 的extern)您收到错误。
    【解决方案4】:

    我能够通过这样做在 TypeScript 中实现自定义错误

    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 };
    

    然后我可以在我的代码库中的任何地方使用它,比如

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

    或者在异步操作中

    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);
        }
    };
    
    

    【讨论】:

    • 这对 the accepted answer 有效。如果将函数命名为Exception,接口命名为IException,则export const ExceptionException 的唯一用途——其他三个引用将是IException
    猜你喜欢
    • 2022-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 2018-11-11
    • 2020-04-04
    • 2017-08-21
    相关资源
    最近更新 更多