从打字稿中的 API 响应正确投射日期

时间:2021-01-12 21:06:49

标签: reactjs typescript axios

我有一个 REST API,它提供以下格式的数据:-

{"id": 1, "name": "New event", "date": "2020-11-14T18:02:00"}

我的前端 React 应用程序中的界面如下:-

export interface MyEvent {
  id: number;
  name: string;
  date: Date;
}

我使用 axios 从 API 获取响应。

const response = await axios.get<MyEvent>("/event/1");
const data = response.data;

但是,由于打字稿的限制,data.date 仍然是一个字符串。

这可能会在代码后期导致问题,我希望所有这些日期字段都是实际的 Date 对象。

我可能会这样做:data.date = new Date(data.date);。但由于很多原因,这不是可行的方法。

有没有更好的方法来处理打字稿中的日期?作为响应,您通常如何处理来自 API 的日期?

2 个答案:

答案 0 :(得分:6)

因此,最适合我的用例的解决方案类似于@Amy 在原始问题的评论中提到的解决方案。

所以我使用 Axios 拦截器将日期转换为 Date 对象。

const client = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_BASE_URL });

client.interceptors.response.use(originalResponse => {
  handleDates(originalResponse.data);
  return originalResponse;
});

export default client;

为了识别日期,我使用了正则表达式,为了转换为 Date 对象,我使用了 date-fns 包。

const isoDateFormat = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d*)?$/;

function isIsoDateString(value: any): boolean {
  return value && typeof value === "string" && isoDateFormat.test(value);
}

export function handleDates(body: any) {
  if (body === null || body === undefined || typeof body !== "object")
    return body;

  for (const key of Object.keys(body)) {
    const value = body[key];
    if (isIsoDateString(value)) body[key] = parseISO(value);
    else if (typeof value === "object") handleDates(value);
  }
}

答案 1 :(得分:0)

我个人使用的一个选项是创建一个实用函数,用于解析从 anyMyEvent 的输入。你可以这样做:

function createMyEvent(data: any): MyEvent {
    return {
        id: data.id,
        name: data.name,
        date: new Date(data.date)
    };
}

然后像这样使用它:

// Same as before, but without a type specified.
const response = await axios.get("/event/1");
// Type is still "MyEvent", but this time its valid.
const data = createMyEvent(response.data);

为了使其完全类型安全,该函数还应验证输入对象以验证它是否具有正确格式的正确字段。如果您担心 API 可能会更改 MyEvent 的架构而不会对客户端进行匹配的更改,则这一点尤其重要。

如果您在启用了 Record<string, unknown> 的代码库中工作,如果需要,您还可以使用 any 代替 noExplicitAny。这两种方法都需要在 createMyEvent 中添加额外的类型断言,但基本思想保持不变。