Express 和 Typescript - Error.stack 和 Error.status 属性不存在

Posted

技术标签:

【中文标题】Express 和 Typescript - Error.stack 和 Error.status 属性不存在【英文标题】:Express and Typescript - Error.stack and Error.status properties do not exist 【发布时间】: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 指出我可以将错误状态放在响应对象上。但是,我的错误处理机制使用了两步过程:

    创建 404 错误并设置其状态

    将其交给以下通用处理程序:

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

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

【问题讨论】:

【参考方案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 的能力,编译器将无法理解错误的完整形式,因此我认为其他一些更好。

以上是关于Express 和 Typescript - Error.stack 和 Error.status 属性不存在的主要内容,如果未能解决你的问题,请参考以下文章

Express 和 Typescript - Error.stack 和 Error.status 属性不存在

Typescript 2.2 Express req, res 隐含任何

如何将 Typescript、NodeJS 和 Express 应用程序部署到 Heroku

如何在 Typescript 项目中使用 express-mysql-session?

TypeScript 2、React JS 和 Express 服务器端渲染问题

Nodejs/Express/Typescript 需要 module.exports