我正在从快速的REST API返回数据。我想使我与客户端的API通信紧密联系。为此,我试图创建一个函数apiJsonResponse
,通过该函数,我所有返回的数据都将在服务器上传输。这是到目前为止我所拥有的示例:
// Example route 1
router.get('/authorized', (req: Request, res: Response) => {
return apiJsonResponse<{ foo: string }>(res, 200, {
message: 'Success',
data: { foo: 'bar' }
});
});
// Example route 2
router.get('/unauthorized', (req: Request, res: Response) => {
return apiJsonResponse(res, 401, {
message: 'User is not authorized',
isMessageDisplayable: true
});
});
// Type-explicit wrapper around `res.status().json()`
function apiJsonResponse<T = undefined>(res: Response, status: number, body: TBody<T>): Response {
return res.status(status).json(body);
}
// My attempt to type for a 'data-case' and a 'no-data-case'
type TBody<T> = T extends undefined ? IBody : IDataBody<T>;
interface IBody {
message: string; // Event descriptor
isMessageDisplayable?: boolean; // Flag whether or not to show user message
}
interface IDataBody<T> extends IBody {
data: T; // Data payload if query is successful
}
因此,基本上,我正在尝试启用两种类型的数据响应。
情况1:无数据有效载荷。这主要用于4xx / 5xx事件,在该事件中,我返回一条消息并指出是否可显示给最终用户。
情况2。数据有效负载。主要用于返回数据有效载荷的2xx事件。
现在,我要的是让函数apiJsonResponse
require body参数以包含类型为T的数据属性,前提是该函数使用该类型进行调用:{{1} }其中x满足apiJsonResponse<T>(url,{data: x, ... })
。这样,我的客户端可以从这样的路由中获取数据,并期望主体包含相同类型的数据属性(从而可以使我的服务器和客户端与同一接口进行通信)。
相反,如果在未声明任何类型的情况下调用我的函数,则键入脚本将禁止在主体参数中包含数据属性。
我希望上面的代码可以解决问题,但事实并非如此。例如,以下对apiJsonResponse函数的调用未提供任何类型,在主体中包含T
参数,但不会引发打字错误:
data
很显然,我对条件式打字稿的理解很缺乏。我认为通过不提供类型,该函数将采用默认的apiJsonResponse(res, 200, {
message: 'Success sending basic test',
data: { test: 'hello-world' },
isMessageDisplayable: true
});
值(请参见上面的undefined
),并且条件语句<T = undefined>
会在以下情况下返回T extends undefined ? IBody : IDataBody<T>
:没有提供类型。然而,这种情况并非如此;相反,无论是否提供类型,以上代码似乎总是返回IDataBody。
对于此处发生的事情的澄清和/或解决方案将不胜感激!
答案 0 :(得分:0)
好的,我找出了问题和解决方案。原始代码很接近(条件语句不是问题),但是Typescript想要在向apiJsonResponse函数提供具体值的参数时推断类型T,然后根据该推断,选择后一个接口({{ 1}})。
为防止类型推断,可以将类型逻辑基于扩展了第一个类型的第二个类型变量。以下修改为我提供了我想要的确切行为:
IDataBody<T>