Da qualche parte nel vostro progetto avrete qualcosa di simile a questo:
interface Result {
readonly items: readonly ResultItem[] | null;
}
interface ResultItem {
readonly Name : string;
readonly CreatedOn : string | undefined;
readonly Description: string;
}
o questo (o sue varianti):
type Result = {
items?: ResultItem[];
}
interface ResultItem {
Name : string;
CreatedOn? : string;
Description: string;
}
Oppure potrebbe essere un type
invece di un interface
(solo assicurarsi che non si utilizza mai class
per descrivere i dati JSON, come JSON object
i dati non possono essere un class
istanza perché il costruttore non viene mai eseguita).
Inoltre, si dovrebbe essere utilizzando camelCase
non PascalCase
per le proprietà del membro. Quindi, utilizzare nomi come createdOn
invece di CreatedOn
nel tuo generato JSON.
Fortunatamente non c'È bisogno di cambiare i tipi di interfacce, basta cambiare il Dattiloscritto di sicurezza check .CreatedOn
e che Date.parse
non ritorno NaN
. In questo modo:
- Il
result.items ?? []
perché il tuo post implica result.items
è annullabile o forse-undefined
.
- Nota quando si utilizza
map
con un =>
-funzione di stile che potrebbe essere necessario avvolgere oggetto-letterali in ()
così il JS motore non interpretare il {
e }
come bloccare i delimitatori.
const result: Result = ...
const currentDate = new Date();
const newResult = (result.items ?? []).filter( e => {
if( typeof e.CreatedOn === 'string' ) {
const parsed = Date.parse( e.CreatedOn );
if( !isNaN( parsed ) ) {
return ( currentDate - parsed ) > 90;
}
}
return false;
} );
Anche se personalmente mi piacerebbe farlo con un iniziale filter
e map
seguente procedura:
const items = result.items ?? [];
const currentDate = new Date();
const newResult = items
.filter( e => typeof e.CreatedOn === 'string' )
.map( e => ( { ...e, CreatedOn2: Date.parse( e.CreatedOn ) } ) )
.filter( e => !isNaN( e.CreatedOn2 ) )
.filter( e => ( currentDate - e.CreatedOn2 ) > 90 ) );
o ulteriormente semplificato:
const items = result.items ?? [];
const currentDate = new Date();
const newResult = items
.filter( e => typeof e.CreatedOn === 'string' )
.map( e => Object.assign( e, { createdOn2: Date.parse( e.CreatedOn ) )
.filter( e => !isNaN( e.CreatedOn2 ) && ( currentDate - e.CreatedOn2 ) > 90 );
Una soluzione ancora migliore:
Se siete in controllo di come il JSON è generato quindi è possibile garantire che alcune (o tutte) le proprietà dell'elemento saranno sempre (e quindi mai undefined
o null
), quindi se si può garantire che tutte e 3 le proprietà sono sempre insieme (mai null
o undefined
) e quindi aggiornare l'tipi di interfacce per questo:
interface ResultItem {
readonly name : string;
readonly createdOn : string;
readonly description: string;
}
- Nota il
camelCase
proprietà.
- L'immutabilità di dati è un vantaggio enorme, in modo da assicurarsi che la proprietà di interfaccia sono tutti
readonly
, tutte le matrici sono readonly T[]
e che le proprietà sono solo annotato con ?
o | null
o | undefined
come appropriato, invece di semplicemente supponendo che in un modo o in un altro.
Quindi, assicurarsi che si utilizza strictNullChecks
nel tsconfig.json
o tsc
opzioni! - in realtà, basta usare strict
sempre!
Anche pensare di cambiare la tua JSON DTO dall'utilizzo di un string
rappresentazione di una Data (ci sono garanzie circa il fuso orario?) per essere un nativo leggibile Unix timestamp (in millisecondi), in questo modo si possono evitare problemi con Date.parse
interamente:
ad esempio:
Risultato.cs:
public class ResultItem
{
[JsonProperty( "createdOn" )]
public DateTimeOffset CreatedOn { get; }
[JsonProperty( "createdOnUnix" )]
public Int64 CreatedOnUnix => this.CreatedOn.ToUnixTimeMilliseconds();
}
Risultato.ts:
interface ResultItem {
readonly createdOn : string;
readonly createdOnUnix: number;
}
const ninetyDaysAgo = new Date();
ninetyDaysAgo.setDate( ninetyDaysAgo.getDate() - 90 );
const newResult = items.filter( e => new Date( e.createdOnUnix ) < ninetyDaysAgo );
...in questo modo si tratta di una singola linea di lavoro.
Il sopra può essere reso ancora più semplice come timestamp Unix sono solo numeri interi che sono direttamente confrontabili, in modo new Date()
può essere evitato all'interno del filter
in questo modo:
const ninetyDaysAgo = new Date();
ninetyDaysAgo.setDate( ninetyDaysAgo.getDate() - 90 );
const ninetyDaysAgoUnix = ninetyDaysAgo.getTime();
const newResult = items.filter( e => e.createdOnUnix < ninetyDaysAgoUnix );
({ CreatedOn, ...item }) => ({
fare, esattamente? Non ho mai visto la diffusione operatore...
utilizzato in funzione di un elenco di parametri, al tempo stesso, come un oggetto di valore letterale.