如何指定使用Express响应

时间:2018-03-06 10:29:06

标签: typescript express

我正在尝试用TypeScript标准化我的express.js网络应用中的响应,我不太确定,我怎么能全局设置,响应应该是例如这个接口:

{
  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类型?

2 个答案:

答案 0 :(得分:1)

你不能删除一个类型上定义的函数,我们可以使用模块扩充为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',
        },
    });

}

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

答案 1 :(得分:0)

一个好的解决方案,可以确保您在任何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> };