I have a REST API that gives data in the following format:-
{"id": 1, "name": "New event", "date": "2020-11-14T18:02:00"}
And an interface in my frontend React app like this:-
export interface MyEvent {
id: number;
name: string;
date: Date;
}
I use axios to fetch response from the API.
const response = await axios.get<MyEvent>("/event/1");
const data = response.data;
However, data.date
remains a string due to typescript limitations.
This can cause problems later in the code, where I expect all such date fields to be an actual Date object.
I could probably do something like: data.date = new Date(data.date);
. But that won't be feasible approach for a lot of reasons.
Is there a better way of handling dates in typescript? How do you handle dates coming from API in response in general?
JavaScript doesn’t have a concept of type casting because variables have dynamic types. However, every variable in TypeScript has a type. Type castings allow you to convert a variable from one type to another. In TypeScript, you can use the as keyword or <> operator for type castings.
In TypeScript, you can use the as keyword or <> operator for type castings. The following selects the first input element by using the querySelector () method: Since the returned type of the document.querySelector () method is the Element type, the following code causes a compiler error:
Now, to use TypeScript within our web API, we need to install TypeScript as a developer dependency. # The -D option installs typescript as a developer dependency npm install -D typescript TypeScript contains static type definitions, which enables catching errors during compile time.
However, every variable in TypeScript has a type. Type castings allow you to convert a variable from one type to another. In TypeScript, you can use the as keyword or <> operator for type castings.
So the solution that best fits my use case is similar to the one mentioned by @Amy in the original question's comment.
So I use Axios interceptors to convert dates to a Date object.
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;
For identifying dates, I've used a regex expression, and for conversion to Date object, I've date-fns package.
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);
}
}
This subject deserves much more attention than it gets. For me, sanity depends on having all json dates parsed to date objects automagically the moment they show up in my application. The best way to do this is to modify the global JSON object. This is, obviously, a fundamental change to a much-used global api, but it's a change for the better. It works with Axios, without interceptors, and it will also just work if any genius decides to use fetch, or xhr, or whatever else you're having.
Rick Strahl has a robust .js routine for doing just this and I heartily recommend it to the whole world. It's just a pity it's not an npm.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With