Background:
In JavaScript, the Date object is used to represent dates and times and is known for its peculiarities — mutability, complex parsing, and timezone specifics. TypeScript utilizes standard JS types for Date, however, typing and working with dates in strict code requires a special approach.
Problem:
The Date in JavaScript is a mutable object that can create atypical errors (for example, setMonth() mutates the object itself, which can lead to unexpected behavior in code). Additionally, integration with external libraries (moment.js, date-fns, Day.js, etc.) requires strict adherence to type consistency — for example, moment.Instant or specific time wrappers that are incompatible with each other. Sometimes the returned type can be a string or number (timestamp), which leads to errors when annotating types or using APIs.
Solution:
TypeScript types a new Date instance as Date, and all its methods are available. When integrating with other libraries, it is essential to carefully track the types of input and output values — either use explicit casting to Date (for example, new Date(value)), or create custom container types for date and time. To convert between timestamp (number), string, and Date object, types must be strictly specified and functions described with types or interfaces.
Code example:
function toIsoString(d: Date | number | string): string { if (d instanceof Date) return d.toISOString(); if (typeof d === 'number' || typeof d === 'string') return new Date(d).toISOString(); throw new Error('Invalid date'); }
Key features:
Is the "Date" type in TypeScript a simple value type?
No, Date is an object, i.e., a reference type. Comparing dates using == or === does not compare values, only references.
const d1 = new Date('2022-01-01'); const d2 = new Date('2022-01-01'); d1 === d2; // false
Can a string or number be directly assigned to the Date type without reinitialization?
No, the Date type is not compatible with number or string. A new instance must be created: new Date(value).
const d: Date = new Date('2020-01-01'); // const d2: Date = '2020-01-01'; // Type error
Will a function that accepts Date work with objects from external libraries (moment, dayjs)?
No, unless the library explicitly implements casting/compatibility with Date through valueOf/toDate, they are different types, and TypeScript will not recognize them as Date.
import dayjs from "dayjs"; function doSomething(d: Date) { /* ... */ } doSomething(dayjs()); // Error, as the Dayjs type is not compatible with Date
In the code, an argument was accepted as any, and it was later assumed to be Date. In practice, the API returned a timestamp as a string, which caused an error when calling .getFullYear().
Pros:
Cons:
The developer created an explicit type for the parameter (Date | string | number), introduced a type guard, and the function explicitly invoked new Date. The compiler forced the explicit handling of all types.
Pros:
Cons: