Cum pentru a filtra un Script matrice pe baza poate-nedefinit data-ca-string item obiect de proprietate?

0

Problema

API returnează rezultatul ca un obiect cu mai mult de mii de valori în următorul format:

result = {
  "items": [
            {
              "Name": "abc",
              "CreatedOn": "2017-08-29T15:21:20.000Z",
              "Description": "xyz"
            },
            {
              "Name": "def",
              "CreatedOn": "2021-05-21T15:20:20.000Z",
              "Description": "cvb"
            }
          ]
}

Aș dori pentru a filtra elemente în obiect, care sunt mai mult de 90 de zile, fără a fi nevoie pentru a repeta toate elementele, folosind pentru buclă. Cu alte cuvinte aș vrea să fac ceva de genul asta de mai jos, dar acest lucru nu funcționează.

var currentDate = new Date();
var newResult = result.items?.filter(function(i) {
    return ((currentDate - Date.parse(i.CreatedOn)) > 90);
}

Potrivit IDE proprietate CreatedOn este de tip string | undefined așa că se aruncă de eroare: Argument de tip 'string | undefined' nu este atribuie parametru de tip 'string'. Tip 'undefined' nu este atribuie tip 'string'.

javascript typescript
2021-11-24 03:43:04
3

Cel mai bun răspuns

2

Undeva în proiectul dumneavoastră va trebui ceva de genul asta:

interface Result {
    readonly items: readonly ResultItem[] | null;
}

interface ResultItem {
    readonly Name       : string;
    readonly CreatedOn  : string | undefined;
    readonly Description: string;
}

sau asta (sau variante ale acestora):

type Result = {
    items?: ResultItem[];
}

interface ResultItem {
    Name       : string;
    CreatedOn? : string;
    Description: string;
}

Sau poate fi un type în loc de un interface (doar asigurați-vă că nu utilizați niciodată class pentru a descrie date JSON, ca JSON object datele nu pot fi o class exemplu, deoarece constructorul nu ruleaza).

De asemenea, ar trebui să fie folosind camelCasenu PascalCasepentru statele proprietăți. Deci, utilizarea de nume ca createdOn în loc de CreatedOn în generat JSON.

Din fericire, nu Aveți nevoie pentru a schimba tipurile/interfaces, schimbă-ți mașina de Scris pentru a în condiții de siguranță verificați .CreatedOn șiDate.parse nu a returnat NaN. Astfel:

  • La result.items ?? [] o parte este pentru post presupune result.items este null sau poate-undefined.
  • Notă atunci când se utilizează map cu o =>-stil funcție de care ați putea avea nevoie să-și încheie obiect-literali în () deci motorului JS nu se interpreteze { și } ca delimitatori de bloc.
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;
} );

Deși, personal, aș face-o cu o inițială filter și map pașii de mai jos:

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 ) );

sau simplificate în continuare:

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 );

O soluție și mai bună:

  • Dacă sunteți în controlul de modul în care JSON este generat atunci vă puteți asigura că anumite (sau toate) element de proprietăți va fi întotdeauna stabilit (și deci nu undefined sau null), deci, dacă vă pot garanta că toate cele 3 proprietăți sunt întotdeauna setat (nu null sau undefined) apoi actualizați tipuri/interfețe pentru acest lucru:

    interface ResultItem {
        readonly name       : string;
        readonly createdOn  : string;
        readonly description: string;
    }
    
    • Notă camelCase proprietăți.
    • Imutabilitatea de date este un beneficiu imens, astfel încât asigurați-vă că interfața de proprietăți sunt toate readonlytoate matricele sunt readonly T[]și că proprietățile sunt doar adnotat cu ? sau | null sau | undefined ca-caz în loc de pur și simplu presupunând că într-un fel sau altul.
  • Deci, asigurați-vă că utilizați strictNullChecks în tsconfig.json sau tsc opțiuni! - de fapt, trebuie doar să utilizați strict întotdeauna!

  • De asemenea, luați în considerare schimbarea JSON DTO la utilizarea unui string reprezentarea o Data (sunt acolo orice garanțiilor despre orar?) pentru a fi un nativ poate fi citit Unix timestamp (în milisecunde), în acest fel puteți evita problemele cu Date.parse în întregime:

de exemplu:

Rezultatul.cs:

public class ResultItem
{
    [JsonProperty( "createdOn" )]
    public DateTimeOffset CreatedOn { get; }

    [JsonProperty( "createdOnUnix" )]
    public Int64 CreatedOnUnix => this.CreatedOn.ToUnixTimeMilliseconds();
}

Rezultatul.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 );

...așa că e o singură linie de muncă.


Cele de mai sus pot fi făcute chiar mai simplu ca Unix timestamp-uri sunt doar numere întregi, care sunt direct comparabile, deci new Date() pot fi evitate în interiorul filterastfel:

const ninetyDaysAgo = new Date();
ninetyDaysAgo.setDate( ninetyDaysAgo.getDate() - 90 );
const ninetyDaysAgoUnix = ninetyDaysAgo.getTime();

const newResult = items.filter( e => e.createdOnUnix < ninetyDaysAgoUnix );
2021-11-24 04:21:52
1

Presupunând că ai interfețe definite ca asta...

interface Item {
  Name: string,
  Description: string,
  CreatedOn?: string // note the optional "?"
}

interface Result {
  items?: Item[] // also optional according to your code
}

și doriți să filtrați pentru elementele care sunt mai vechi de 90 de zile (cu excepția celor cu nr. CreatedOn), apoi încercați acest

interface ItemWithDate extends Omit<Item, "CreatedOn"> {
  CreatedOn?: Date // real dates, so much better than strings
}

const result: Result = { /* whatever */ }

const items: ItemWithDate[] = result.items?.map(({ CreatedOn, ...item }) => ({
  ...item,
  CreatedOn: CreatedOn ? new Date(CreatedOn) : undefined
})) ?? []

const dateThreshold = new Date()
dateThreshold.setDate(dateThreshold.getDate() - 90)

const newItems = items.filter(({ CreatedOn }) =>
  CreatedOn && CreatedOn < dateThreshold)

Mașina De Scris, Teren De Joacă Pentru Demo

2021-11-24 04:01:43

Scuzati-mi ignoranta (si e o gaura destul de mare de-al meu), ceea ce nu ({ CreatedOn, ...item }) => ({ fac, mai exact? N-am văzut răspândirea operator ... folosit într-o listă de parametri funcție, în același timp, ca un obiect-literal.
Dai

@Dai extracte unele nume de proprietăți (CreatedOn) și păstrează restul în item. Practic o comandă rapidă pentru (obj) => { const { a, b, ...rest } = obj; ...
Phil
-1

codul lipsește ) din funcția de filtru

var currentDate = new Date();
var newResult = result.items?.filter(function(i) {
    return ((currentDate - Date.parse(i.CreatedOn)) > 90);
}  ) //<= misss


2021-11-24 04:23:03

Raspunsul tau nu are adresa tscmodelului tip de erori.
Dai

Așa cum e scrisă, răspunsul este clar. Vă rugăm să editați pentru a adăuga detalii suplimentare, care va ajuta pe alții să înțeleagă cum acest adresează întrebarea. Puteți găsi mai multe informații despre cum să scrie răspunsuri bune în centrul de ajutor.
Community

În alte limbi

Această pagină este în alte limbi

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................