История вопроса:
В JavaScript объект Date используется для представления дат и времени и известен своей спецификой работы — мутируемостью, сложностью парсинга и особенностями таймзонов. TypeScript использует для Date стандартные JS-типы, однако типизация и работа с датой в строгом коде требует особого подхода.
Проблема:
Date в JavaScript — мутируемый объект, который может создавать нетипичные ошибки (например, setMonth() мутирует сам объект, что может привести к неожиданному поведению кода). Кроме того, интеграция с внешними библиотеками (moment.js, date-fns, Day.js и др.) требует соблюдать точность типов — например, moment.Instant или специфические обёртки времени, несовместимые между собой. Иногда возвращаемый тип может быть string или number (timestamp), что ведёт к ошибкам при аннотировании типов или использовании API.
Решение:
TypeScript типизирует новый экземпляр Date как Date, и все его методы доступны. При интеграции с другими библиотеками важно тщательно следить за типами входных и выходных значений — использовать явное приведение к Date (например, new Date(value)), либо создавать пользовательские типы-контейнеры для даты и времени. Для конвертации между timestamp (number), строкой и объектом Date нужно строго указывать типы и описывать функции типами или интерфейсами.
Пример кода:
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'); }
Ключевые особенности:
Является ли тип "Date" в TypeScript простым value type?
Нет, Date — это объект, т.е. reference type. Сравнение дат через == или === не сравнивает значения, только ссылки.
const d1 = new Date('2022-01-01'); const d2 = new Date('2022-01-01'); d1 === d2; // false
Можно ли напрямую присваивать строку или число типу Date без новой инициализации?
Нет, тип Date не совместим с number или string. Необходимо создавать новый экземпляр: new Date(value).
const d: Date = new Date('2020-01-01'); // const d2: Date = '2020-01-01'; // Ошибка типизации
Будет ли функция, принимающая Date, работать с объектами внешних библиотек (moment, dayjs)?
Нет, unless в библиотеке явно реализовано приведение/совместимость с Date через valueOf/toDate, это разные типы, и TypeScript не поймёт их как Date.
import dayjs from "dayjs"; function doSomething(d: Date) { /* ... */ } doSomething(dayjs()); // Ошибка, т.к. тип Dayjs не совместим c Date
В коде принимался аргумент как any, а далее предполагалось, что это Date. На практике API возвращал timestamp в string, что вызывало ошибку при вызове .getFullYear().
Плюсы:
Минусы:
Разработчик создал явный тип для параметра (Date | string | number), ввёл type guard, и функция вызывала new Date явно. Компилятор вынуждает явно обрабатывать все типы.
Плюсы:
Минусы: