Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save MrChocolatine/367fb2a35d02f6175cc8ccb3d3a20054 to your computer and use it in GitHub Desktop.
Save MrChocolatine/367fb2a35d02f6175cc8ccb3d3a20054 to your computer and use it in GitHub Desktop.
TypeScript – How to accurately type dates in ISO 8601 format
// 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`;
@joekrump
Copy link

Here's what I've been using:

type oneToNine = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
type d = oneToNine | 0;
type YYYY = `19${d}${d}` | `20${d}${d}`;
type MM = `0${oneToNine}` | `1${0 | 1 | 2}`;
type DD = `${0}${oneToNine}` | `${1 | 2}${d}` | `3${0 | 1}`;
type DateYMString = `${YYYY}-${MM}`;
type THours = `${number}${number}`;
type TMinutes = `${number}${number}`;
type TSeconds = `${number}${number}`;
type TMilliseconds = `${number}${number}${number}`;

// type: DateYMD ex. "2021-01-01"
export type DateYMD = `${DateYMString}-${DD}`;

/**
 * type: TDateISOTime ex. "14:42:34.678"
 */
type TDateISOTime = `${THours}:${TMinutes}:${TSeconds}.${TMilliseconds}`;

/**
 * type: DateYMDZoneString ex. "2021-01-01T14:42:34.678Z"
 */
export type ISO8601 = `${DateYMD}T${TDateISOTime}Z`;

My aim was not to make this perfect but to help point people in the right direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment