Historia del tema:
En JavaScript, el objeto Date se utiliza para representar fechas y horas y se conoce por su especificidad en cuanto a funcionamiento: mutabilidad, complejidad de análisis y características de zonas horarias. TypeScript utiliza los tipos estándar de JS para Date, sin embargo, la tipificación y el trabajo con fechas en código estricto requiere un enfoque particular.
Problema:
Date en JavaScript es un objeto mutable, que puede generar errores atípicos (por ejemplo, setMonth() muta el propio objeto, lo que puede provocar un comportamiento inesperado en el código). Además, la integración con bibliotecas externas (moment.js, date-fns, Day.js, etc.) requiere mantener la precisión de los tipos; por ejemplo, moment.Instant o envolturas de tiempo específicas que son incompatibles entre sí. A veces, el tipo devuelto puede ser string o number (timestamp), lo que lleva a errores al anotar tipos o usar API.
Solución:
TypeScript tipifica una nueva instancia de Date como Date, y todos sus métodos son accesibles. Al integrarse con otras bibliotecas, es importante vigilar de cerca los tipos de los valores de entrada y salida: usar conversiones explícitas a Date (por ejemplo, new Date(value)), o crear tipos contenedores personalizados para fechas y horas. Para la conversión entre timestamp (número), cadena y objeto Date, se deben especificar rigurosamente los tipos y describir las funciones con tipos o interfaces.
Ejemplo de código:
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('Fecha inválida'); }
Características clave:
¿Es el tipo "Date" en TypeScript un tipo de valor simple?
No, Date es un objeto, es decir, un tipo de referencia. La comparación de fechas a través de == o === no compara valores, solo referencias.
const d1 = new Date('2022-01-01'); const d2 = new Date('2022-01-01'); d1 === d2; // false
¿Se puede asignar directamente una cadena o un número al tipo Date sin una nueva inicialización?
No, el tipo Date no es compatible con number o string. Es necesario crear una nueva instancia: new Date(value).
const d: Date = new Date('2020-01-01'); // const d2: Date = '2020-01-01'; // Error de tipificación
¿Funciona una función que acepta Date con objetos de bibliotecas externas (moment, dayjs)?
No, a menos que la biblioteca implemente explícitamente la conversión o compatibilidad con Date a través de valueOf/toDate, son tipos diferentes y TypeScript no los entenderá como Date.
import dayjs from "dayjs"; function doSomething(d: Date) { /* ... */ } doSomething(dayjs()); // Error, ya que el tipo Dayjs no es compatible con Date
En el código, se aceptó un argumento como any, y luego se supuso que era un Date. En la práctica, la API devolvía un timestamp en string, lo que causaba un error al llamar a .getFullYear().
Pros:
Contras:
El desarrollador creó un tipo explícito para el parámetro (Date | string | number), introdujo un type guard, y la función invocó new Date de manera explícita. El compilador obliga a procesar explícitamente todos los tipos.
Pros:
Contras: