J'essaie de convertir un projet node.js existant de javascript en TypeScript. J'utilise le capteur d'erreur 404 par défaut du modèle Visual Studio Express 4:
// catch 404 and forward to error handler
app.use(function (req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
Cependant, je reçois le message d'erreur suivant: La propriété 'status' n'existe pas sur le type 'Error'.
J'obtiens un message similaire si j'essaie d'invoquer la propriété .stack de l'erreur: La propriété 'stack' n'existe pas sur le type 'Error'.
Est-ce que quelqu'un sait ce qui se passe ici?
Edit: Steve Fenton souligne que je pourrais simplement mettre le statut d'erreur sur l'objet de réponse. Cependant, mon mécanisme de gestion des erreurs utilise un processus en deux étapes:
Remettez-le au gestionnaire générique suivant:
app.use(function (err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
Ainsi, le statut d'erreur est d'abord défini sur l'objet Error, puis relu par le gestionnaire d'erreurs pour décider comment gérer l'erreur.
Vous pouvez dire à TypeScript que pour votre cas d'utilisation Error
peut avoir un status
dessus:
interface Error{
status?: number;
}
Vous obtenez donc:
interface Error{
status?: number;
}
var err = new Error('Not Found');
err.status = 404;
Cependant, je dois dire que votre code express n'est pas idiomatique, mais TypeScript peut le comprendre, si vous en parlez.
Vous mettez le code d'erreur sur la réponse ...
app.use(function (req, res, next) {
var err = new Error('Not Found');
res.status(404)
next(err);
});
La meilleure façon, à mon avis, n'est pas de désactiver les vérifications de type en définissant l'erreur sur any
, ou en créant un nouveau type Error
, car il en existe déjà un dans @types/node
.
Au lieu de cela, vous devez étendre ce type d'erreur:
interface ResponseError extends Error {
status?: number;
}
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
});
});
Il s'agit généralement de savoir comment initialiser des objets paresseusement en TypeScript.
La façon idéale de le faire est:
interface ErrorWithStatus extends Error {
status: string
}
let foo = new Error() as ErrorWithStatus;
foo.status = '404';
L'utilisation de any
, ou d'interfaces avec des champs nullables, vous laisse avec des contrats inférieurs et faibles.
Une autre option dans TypeScript:
const err: { status?: number, message:string } = new Error('Not Found');
err.status = 404;
Une autre option dans TypeScript:
let err: any;
err = new Error();
err.status = 404;
Si je ne me trompe pas, il est toujours préférable d'obtenir le type qui est réellement attendu. Je n'ai trouvé aucun support dur que j'ai raison, mais j'utilise:
import createError, { HttpError } from 'http-errors';
et pour être complet pour tous les types j'importe aussi les types de paramètres d'utilisation:
import express, { Request, Response, NextFunction } from 'express';
La fonction réelle que j'utilise ressemble alors à ceci:
app.use((err: HttpError, req: Request, res: Response, next: NextFunction) => { ... }
Dans votre cas, si vous souhaitez créer votre propre erreur:
app.use((req: Request, res: Response, next: NextFunction) => {
next(createError(404));
});
ou plus proche de votre code:
app.use((req: Request, res: Response, next: NextFunction) => {
let err = new HttpError('Not found');
err.status = 404;
next(err);
});
Je suis juste allé pour
var err = new Error('Not Found');
err['status'] = 404;