ProgramaciónDesarrollador Full Stack

Describe cómo funciona la tipificación Date y los errores de tiempo en TypeScript. ¿Cómo se deben describir los tipos correctos para trabajar con fechas y horas, y qué problemas pueden surgir al integrarse con bibliotecas externas o el Date nativo?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

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:

  • Date es un objeto mutable, no un tipo de valor, sino un tipo de referencia.
  • La recepción y retorno de fechas desde API o bibliotecas externas requiere mantener estrictamente la compatibilidad de tipos.
  • Las envolturas externas como moment o dayjs requieren tipos personalizados explícitos y/o funciones de tipo guard.

Preguntas engañosas.

¿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

Errores típicos y anti-patrones

  • Uso de cualquier tipo (any) para fechas al integrarse con API.
  • Mutación del objeto Date (set*, setUTC*) al pasarlo a varias funciones — riesgo de condición de carrera.
  • Incompatibilidad de tipos: intentar trabajar con un tipo externo como si fuera Date.

Ejemplo de la vida real

Caso negativo

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:

  • Trabajo "con todo" sin errores de compilación.

Contras:

  • Riesgo de errores en tiempo de ejecución.
  • Dificultades para atrapar errores en producción.

Caso positivo

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:

  • Errores claros ya en la etapa de compilación.
  • El trabajo es más confiable con diferentes tipos de entrada de fecha.

Contras:

  • Un poco más de código de plantilla (type guards).
  • Requiere profundizar en la estructura de tipos de bibliotecas externas.