Storia della questione:
In JavaScript l'oggetto Date viene utilizzato per rappresentare date e ore ed è noto per la sua specificità di funzionamento: mutabilità, complessità di parsing e peculiarità nei fusi orari. TypeScript utilizza per Date i tipi JS standard, tuttavia la tipizzazione e la gestione delle date nel codice rigoroso richiede un approccio speciale.
Problema:
Date in JavaScript è un oggetto mutabile, che può creare errori atipici (ad esempio, setMonth() muta l'oggetto stesso, il che può portare a comportamenti imprevisti del codice). Inoltre, l'integrazione con librerie esterne (moment.js, date-fns, Day.js, ecc.) richiede di mantenere la precisione dei tipi: ad esempio, moment.Instant o specifici wrapper temporali, non compatibili tra loro. A volte il tipo restituito può essere string o number (timestamp), il che porta a errori nella annotazione dei tipi o nell'uso delle API.
Soluzione:
TypeScript tipizza una nuova istanza di Date come Date, e tutti i suoi metodi sono disponibili. Durante l'integrazione con altre librerie è importante monitorare attentamente i tipi dei valori di input e output: utilizzare il casting esplicito a Date (ad esempio, new Date(value)), oppure creare tipi contenitore personalizzati per date e orari. Per la conversione tra timestamp (number), stringa e oggetto Date, è necessario specificare rigorosamente i tipi e descrivere le funzioni con tipi o interfacce.
Esempio di codice:
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('Data non valida'); }
Caratteristiche chiave:
Il tipo "Date" in TypeScript è un semplice tipo value?
No, Date è un oggetto, cioè un tipo reference. Il confronto delle date tramite == o === non confronta i valori, solo i riferimenti.
const d1 = new Date('2022-01-01'); const d2 = new Date('2022-01-01'); d1 === d2; // false
È possibile assegnare direttamente una stringa o un numero al tipo Date senza una nuova inizializzazione?
No, il tipo Date non è compatibile con number o string. È necessario creare una nuova istanza: new Date(value).
const d: Date = new Date('2020-01-01'); // const d2: Date = '2020-01-01'; // Errore di tipizzazione
Funzionerà una funzione che accetta Date con oggetti di librerie esterne (moment, dayjs)?
No, a meno che nella libreria non sia implementato esplicitamente il casting/compatibilità con Date tramite valueOf/toDate, sono tipi diversi e TypeScript non li riconoscerà come Date.
import dayjs from "dayjs"; function doSomething(d: Date) { /* ... */ } doSomething(dayjs()); // Errore, poiché il tipo Dayjs non è compatibile con Date
Nel codice l'argomento è stato accettato come any, e poi si presumeva che fosse Date. In pratica l'API restituiva un timestamp in stringa, il che ha causato un errore quando si chiamava .getFullYear().
Vantaggi:
Svantaggi:
Lo sviluppatore ha creato un tipo esplicito per il parametro (Date | string | number), ha introdotto un type guard, e la funzione ha richiamato new Date in modo esplicito. Il compilatore costringe a gestire esplicitamente tutti i tipi.
Vantaggi:
Svantaggi: