打字稿:'new' 表达式,其目标缺少构造签名,隐式具有 'any' type.ts(7009)

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

以下代码最适合在 Chrome Devtools、Node.js 等中显示自定义错误。基于 this Whosebug 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 classes。我不想将 classes 转换为 ES6,因为我正在创建一个轻量级库,而 class polyfill 本身就占我整个代码大小的 10%。

总而言之,我该如何注释我现在的代码?

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

您可以声明 class,但要用一个函数来实现它。这样输出(结果 javascript)不会受到影响,但打字稿会将 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 中实现自定义错误
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);
    }
};