Using Typescript to recursively convert dates to strings
If you work with TypeScript you may be familiar with “utility types”, which take a given type and transform it somehow into a different type. It’s a function which takes a type as an input and modifies it and returns a new type. TypeScript has many built-in utility types, which are detailed here: TypeScript’s introductory article on utility types
The built-in utility types are great, but you can also make your own. Here’s one we’ve made which is extra special:
type RecursivelyConvertDatesToStrings<T> = T extends Date ? string : T extends Array<infer U> ? RecursivelyConvertDatesToStrings<U>[] : T extends object ? { [K in keyof T]: RecursivelyConvertDatesToStrings<T[K]> } : T;
This is a utility type which takes anything you throw at it, objects, arrays, primitives, you name it, and converts Date
values to string
. It’ll then be strings-for-dates all the way down
Fun fact
One of our engineers, Open tweet->, implemented this utility type, with the help of GitHub’s AI code-writing-assistant, Copilot.
Open tweet->
Our use case: server-side vs. client-side typing
We use RecursivelyConvertDatesToStrings
to transform the typings of our endpoint responses (typically ORM models arranged and prepped in one form or another) from how they look server-side, into how they arrive client-side, upon a fetch
operation. Because our endpoints return data via JSON in the standard way, there’s no way for any Date
fields to arrive in-tact. They’re necessarily flattened into strings for the HTTP response.
So, we type our “fetched endpoint responses”, by taking our server-side “endpoint responses” and running them through this utility type. That way TypeScript knows that all our favorite date fields, such as createdAt
or updatedAt
are now of string
type, and our client-side state and rendering code set up for success.
You may not have this use case though
Some applications might benefit from a client-side layer which automatically intercepts fetched payloads and reconstitutes proper JavaScript Date
objects from strings that match a date. We considered this, but decided that for our needs, it’s sufficient to do any Date
reconstitution manually, as needed, for a given operation client-side.
References
Invite only
We're building the next generation of data visualization.
How to turn webpages into editable canvases with a JavaScript bookmarklet
Kris Lachance
How to fix the "not all code paths return a value" issue in TypeScript
Kris Lachance
Working with WebSockets in Node.js using TypeScript
Kris Lachance
Type Annotations Can Only Be Used in TypeScript Files
Kris Lachance
Guide to TypeScript Recursive Type
Kris Lachance
How to Configure Knex.js with TypeScript
Kris Lachance