Typescript 如何指定Express响应返回的类型

Typescript 如何指定Express响应返回的类型,typescript,express,Typescript,Express,我正在尝试用TypeScript标准化我的express.js web应用程序中的响应,但我不太确定如何全局设置响应,例如此界面: { success: boolean, data?: any, error?: string, } 现在我正在写: async (req: Request, res: Response, next: NextFunction) => { try { registerResponse = await register(req.body.

我正在尝试用TypeScript标准化我的express.js web应用程序中的响应,但我不太确定如何全局设置响应,例如此界面:

{
  success: boolean,
  data?: any,
  error?: string,
}
现在我正在写:

async (req: Request, res: Response, next: NextFunction) => {
  try {
    registerResponse = await register(req.body.email, req.body.password);
  } catch (error) {
    return res.json({
      success: false,
      error: error.message,
    });
  }

  return res.json({
    success: true,
    data: {
      message: 'Account registered',
    },
  });
};

有没有办法设置其他设置,或者重写typedef以实现硬编码的res.json类型?

您不能删除在类型上定义的函数,我们可以通过模块扩展为
json
函数添加重载,但是这几乎没有什么用处,因为如果我们把属性搞错了,编译器会选择函数的原始版本,允许任何修改

一个更激进的方法是创建一个与
Response
兼容的新类型,但它删除了原始的
json
方法,并用类型化版本替换它。我们可以使用映射类型,这样就不会复制任何原始类型:

// Helpers
type Diff<T extends string, U extends string> = ({ [P in T]: P } & { [P in U]: never } & { [x: string]: never })[T];
type Omit<T, K extends keyof T> = Pick<T, Diff<keyof T, K>>;

// Generic typed response, we omit 'json' and we add a new json method with the desired parameter type
type TypedResponse<T> = Omit<Response, 'json'> & { json(data: T): Response };
// An example of a typed response
type AppResponse = TypedResponse<{
    success: boolean,
    data?: any,
    error?: string,
}>

app.get('/', async (req: Request, res: AppResponse, next: NextFunction) => {
    try {
        // ....
    } catch (error) {

        return res.json({
            success: false,
            error: error.message,
            errors: "" // causses error
        });
    }

    return res.json({
        success: true,
        data: {
            message: 'Account registered',
        },
    });

}
//助手
类型Diff=({[P in T]:P}&{[P in U]:never}&{[x:string]:never}[T];
类型省略=拾取;
//泛型类型响应,我们省略了“json”,并添加了一个具有所需参数类型的新json方法
类型TypedResponse=Omit&{json(数据:T):Response};
//类型化响应的示例
类型AppResponse=TypedResponse
app.get('/',异步(req:Request,res:AppResponse,next:NextFunction)=>{
试一试{
// ....
}捕获(错误){
返回res.json({
成功:错,
错误:error.message,
错误:“”//导致错误
});
}
返回res.json({
成功:没错,
数据:{
消息:“帐户已注册”,
},
});
}

不幸的是,没有办法强迫开发人员使用通用版本(长棒除外),但是通过代码审查,这可能对您来说已经足够好了。

这是一个很好的解决方案,可以确保您在任何TypeDoc文档中都有正确的API响应,但是如果您使用如下方法链接,它就不起作用: res.status(200).json(..),因为您仍将使用原始的类型化json()函数。因此,您还需要重新声明计划使用的任何方法,并确保它们返回新的自定义类型,如下所示:

type TypedResponse<T> = Omit<express.Response, 'json' | 'status'> & { json(data: T) : TypedResponse<T> } & { status(code: number): TypedResponse <T> };
TypedResponse=Omit&{json(数据:T):TypedResponse}&{status(代码:number):TypedResponse};