Last active
March 21, 2025 16:39
-
-
Save MrChocolatine/367fb2a35d02f6175cc8ccb3d3a20054 to your computer and use it in GitHub Desktop.
TypeScript – How to accurately type dates in ISO 8601 format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// In TS, interfaces are "open" and can be extended | |
interface Date { | |
/** | |
* Give a more precise return type to the method `toISOString()`: | |
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString | |
*/ | |
toISOString(): TDateISO; | |
} | |
type TYear = `${number}${number}${number}${number}`; | |
type TMonth = `${number}${number}`; | |
type TDay = `${number}${number}`; | |
type THours = `${number}${number}`; | |
type TMinutes = `${number}${number}`; | |
type TSeconds = `${number}${number}`; | |
type TMilliseconds = `${number}${number}${number}`; | |
/** | |
* Represent a string like `2021-01-08` | |
*/ | |
type TDateISODate = `${TYear}-${TMonth}-${TDay}`; | |
/** | |
* Represent a string like `14:42:34.678` | |
*/ | |
type TDateISOTime = `${THours}:${TMinutes}:${TSeconds}.${TMilliseconds}`; | |
/** | |
* Represent a string like `2021-01-08T14:42:34.678Z` (format: ISO 8601). | |
* | |
* It is not possible to type more precisely (list every possible values for months, hours etc) as | |
* it would result in a warning from TypeScript: | |
* "Expression produces a union type that is too complex to represent. ts(2590) | |
*/ | |
type TDateISO = `${TDateISODate}T${TDateISOTime}Z`; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This approach is somewhat flawed. ISODate isn't a type—it's a format. The actual type would still be a string.
According to the ISO 8601 standard, timezones can include a
Z
to indicate UTC or an offset.. For example, you could define a type like this:The Offset can actually be empty (eg.
2021-01-01T14:42:34.678
) which is implicit +0 = Z.That said, it's important to differentiate between types and validators. What you’re really looking for here is a validator, such as:
In my opinion, it's best to avoid relying heavily on ISODate formats. Instead, work with
Date
objects in your application logic, and if you need to transfer data, use a more reliable format like epoch milliseconds (UTC).I'm currently just using:
If Typescript ever decided to add a type for ISODate (highly doubt that) then this method would just return it as is.