【发布时间】:2021-12-25 15:04:24
【问题描述】:
我正在尝试为调用 Express'es 链 res.status(..).json(..) 的函数实现类型断言包装器。我想我“已经在那里”,但我卡住了。目标是静态检查是否:
- 传递的 HTTP 状态代码符合特定的响应负载
- 响应载荷具有一定的价值
TypeScript Playground 演示(完整实现尝试): click
其中一个错误来自我在上面链接的 TS 演示代码 [x] 中收到的列表:
类型“THTTPStatusCodeToData”上不存在属性“200”
包装器实现是:
function responseWrapper<
DataKey extends keyof IEmbracedResponse
>(
res: Res,
status: keyof typeof mappedHTTPStatusCode,
data: Record<
DataKey,
THTTPStatusCodeToData[typeof status] // <-- so far, problem is here [x]
>
) {
return res.status(status).json(data); // just a chain call, but TS asserts correct `data` type for certain `status`
}
使用示例:
router.get('/', (req: Request, res: Response) => {
if (!req.body.login) {
return responseWrapper(res, 400, { error: 'Request payload lacks of "login"!' });
}
return responseWrapper(res, 200, { payload: { isAdmin: true }});
})
示例输入和 TS 预期类型检查结果:
responseWrapper(res, 200, { exception: Error('ups') }); // <-- fail, because 'exception' key cannot be associated with 200 status
responseWrapper(res, 500, { exception: 'something crashed'}); // <-- fail, because 'exception' cannot be a string, but Error object
responseWrapper(res, 200, { something: null}); // <-- fail, because status 200 cannot be associated with 'something' key
responseWrapper(res, 500, { error: 'ups' }); // <-- fail, because status 500 must be associated with 'exception' key, not the 'error' key
responseWrapper(res, 200, { payload: { isAdmin: true }}); // <-- ok, because status 200 can be associated with 'payload' key and the payload has object value
responseWrapper(res, 500, { exception: Error('ups') }); // <-- ok, because status 500 can be associated with 'exception' key and the value is Error object
responseWrapper(res, 400, { error: 'ups' }); // <-- ok, because status 400 can be associated with 'error' key and it's a string
到目前为止,我使用了不太高级的包装器,只是为了检查传递的对象值是否与键正确关联,但现在我还希望获得关于值关联检查的 HTTP 状态:
const embraceResponse = <
Key extends keyof IEmbracedResponse
>(response: Record<Key, IEmbracedResponse[Key]>) =>
response;
// usage examples:
res.status(200).json(embraceResponse({ payload: { prop: true } }));
res.status(400).json(embraceResponse({ error: 'ups' }));
【问题讨论】:
标签: typescript response wrapper http-status-codes payload