【问题标题】:Express and Typescript - Error.stack and Error.status properties do not existExpress 和 Typescript - Error.stack 和 Error.status 属性不存在
【发布时间】:2015-05-01 19:40:08
【问题描述】:

我正在尝试将现有的 node.js 项目从 javascript 转换为 typescript。我一直在使用 Visual Studio Express 4 模板中的默认 404 错误捕获器:

// catch 404 and forward to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

但是,我收到以下错误消息: 类型“错误”上不存在属性“状态”。

如果我尝试调用错误的 .stack 属性,我会收到类似的消息: “错误”类型上不存在属性“堆栈”。

有人知道这里发生了什么吗?

编辑: Steve Fenton 指出我可以将错误状态放在响应对象上。但是,我的错误处理机制使用了两步过程:

  1. 创建 404 错误并设置其状态
  2. 将其交给以下通用处理程序:

    app.use(function (err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: {}
        });
    });
    

所以首先在Error对象上设置错误状态,然后由错误处理程序回读以决定如何处理错误。

【问题讨论】:

    标签: javascript node.js express typescript


    【解决方案1】:

    扩展全球Error

    你可以告诉 TypeScript 对于你的用例Error 可能有一个status

    interface Error {
        status?: number;
    }
    

    所以你得到:

    interface Error {
        status?: number;
    }
    
    var err = new Error('Not Found');
    err.status = 404;
    

    另类

    将状态放在res 上并发送err。例如:

    // catch 404 and forward to error handler
    app.use(function (req, res, next) {
        var err = new Error('Not Found');
        res.status(404); // using response here
        next(err);
    });
    

    【讨论】:

    • 谢谢巴萨拉特。我只是假设这是一种适当的做事方式,因为它是在 Visual Studio Express 4 模板中完成的。
    • 哎哟。 糟糕的视觉工作室团队
    • 这个模板,是js模板还是typescript模板?
    • OP 的代码在 Express 方面看起来很惯用(每个 [expressjs.com/en/guide/error-handling.html],即res.statusCode 设置自 err.status(或 err.statusCode)。(也headers) - 但是 Express 类型不应该包含类似:declare global { // Shouldn't Express do this? interface Error { status?: number; statusCode?: number; headers: [string] } } 的内容吗?(抱歉格式不好) - 是否已经在某个地方讨论过这个问题?
    • 你如何告诉 typescript Error 上面有 status
    【解决方案2】:

    在我看来,最好的方法不是通过将错误设置为any 来禁用类型检查,或者创建一个新的Error 类型,因为@types/node 中已经存在一个类型。

    相反,您应该扩展该错误类型:

    interface ResponseError extends Error {
      status?: number;
    }
    

    【讨论】:

    • 我会推荐上面的方法,它对我来说看起来更复杂
    • 有什么方法可以让我在全球范围内做到这一点?
    • 我认为接受的答案可以满足您的需要
    【解决方案3】:

    您将错误代码放在响应中...

    app.use(function (req, res, next) {
        var err = new Error('Not Found');
        res.status(404)
        next(err);
    });
    

    【讨论】:

      【解决方案4】:
      import * as express from 'express';
      interface Error {
        status?: number;
        message?: string;
      }
      
      app.use((err: Error, req: express.Request, res: express.Response, next: express.NextFunction) => {
        res.status(err.status || 500);
        res.render('error', {
          message: err.message,
          error: err
        });
      });
      

      【讨论】:

      • 如果你用一些词来帮助 OP 理解你的代码的哪一部分解决了他们的问题,它会得到一个更好的答案。
      【解决方案5】:

      这一般是关于如何在 Typescript 中懒惰地初始化对象的问题。

      理想的方法是:

      interface ErrorWithStatus extends Error {
          status: string
      }
      
      let foo = new Error() as ErrorWithStatus;
      foo.status = '404';
      

      使用any,或带有可为空字段的接口,会让你的合约低于标准和弱。

      【讨论】:

      • 应该是as ErrorWithStatus。但你得到了我的支持:-)
      【解决方案6】:

      如果我没记错的话,最好总是得到实际预期的类型。我找不到任何正确的支持,但我使用:

      import createError, { HttpError } from 'http-errors';
      

      为了所有类型的完整,我还导入了使用的参数类型:

      import express, { Request, Response, NextFunction } from 'express';
      

      我使用的实际函数如下所示:

      app.use((err: HttpError, req: Request, res: Response, next: NextFunction) => { ... }
      

      如果您想创建自己的错误:

      app.use((req: Request, res: Response, next: NextFunction) => {
        next(createError(404));
      });
      

      或更接近您的代码:

      app.use((req: Request, res: Response, next: NextFunction) => {
        let err = new HttpError('Not found');
        err.status = 404;
        next(err);
      });
      

      【讨论】:

        【解决方案7】:

        TypeScript 中的另一个选项:

        let err: any;
        err = new Error();
        err.status = 404;
        

        【讨论】:

        • 创建类型any 完全放弃了Typescript 的最大优势之一——类型检查和执行。这个解决方案可能首先违背了 OP 从 JavaScript 切换到 Typescript 的目标。我认为其他一些更好
        【解决方案8】:

        TypeScript 中的另一个选项:

        const err: { status?: number, message:string } = new Error('Not Found');
        err.status = 404;
        

        【讨论】:

        • 我认为扩展 Error 是一个更好的解决方案,因为它允许 TypeScript 编译器理解实例化对象的完整形状。此解决方案将理解仅限于状态和消息属性。
        【解决方案9】:

        我刚去

        var err = new Error('Not Found');
        err['status'] = 404;
        

        【讨论】:

        • OP 正在使用 TypeScript。此解决方案将放弃使用智能感知/自动完成 b/c 的能力,编译器将无法理解错误的完整形式,因此我认为其他一些更好。
        猜你喜欢
        • 2020-01-22
        • 2020-12-13
        • 1970-01-01
        • 1970-01-01
        • 2021-06-27
        • 2018-08-15
        • 2018-02-02
        • 2021-03-14
        • 2018-07-31
        相关资源
        最近更新 更多