Ako filter a Strojom pole na základe možno-undefined dátum-ako-string položka objekt nehnuteľnosti?

0

Otázka

API vráti výsledok ako objekt s viac ako tisíc hodnoty v nasledujúcom formáte:

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

Ja by som na položky filtra v objekte, ktoré sú viac ako 90 dní bez toho, aby museli opakovať všetky položky pomocou slučky. Inými slovami by som chcel robiť niečo, ako je to uvedené nižšie, ale to nefunguje.

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

Podľa IDE vlastníctva CreatedOn je typu string | undefined tak to vyhodí chybu: Argument typu 'string | undefined' nie je priraditeľný k parametrom typu 'string'. Druh 'undefined' nie je priraditeľný k typu 'string'.

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

Najlepšiu odpoveď

2

Niekde v projekte budete mať niečo ako toto:

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

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

alebo tento (alebo ich variácie):

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

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

Alebo to môže byť type miesto interface (len uistite sa, že ste nikdy nemali používať, class opísať JSON údajov, ako JSON object údaje nemôžu byť class stupňa, pretože konštruktér nikdy beží).

Tiež by ste mali používať camelCasenie PascalCasepre členské vlastnosti. Takže používať mená ako createdOn namiesto CreatedOn vo vašom generované JSON.

Našťastie nemusíte zmeniť typy/interfaces, stačí zmeniť svoje Strojom, aby bezpečne kontrola .CreatedOn a že Date.parse nevrátila NaN. Tak ako:

  • Na result.items ?? [] súčasťou je preto, že váš príspevok znamená result.items je nullable alebo možno-undefined.
  • Poznámka pri používaní map s =>-štýl funkcie, ktoré budete musieť zabaliť objekt-literály v () tak JS engine nemá interpretovať { a } ako blok oddeľovače.
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;
} );

Aj keď osobne by som to s počiatočným filter a map postup:

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

alebo zjednodušené ďalej:

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

Ešte lepšie riešenie:

  • Ak ste v ovládacom ako JSON je generovaný potom môžete zabezpečiť, že niektoré (alebo všetky) položku vlastnosti sa vždy možné nastaviť (a tak nikdy undefined alebo null), takže ak môžete zaručiť, že všetky 3 vlastnosti sú vždy nastavené (nikdy null alebo undefinedpotom aktualizovať typy/interfaces na toto:

    interface ResultItem {
        readonly name       : string;
        readonly createdOn  : string;
        readonly description: string;
    }
    
    • Poznámka: camelCase vlastnosti.
    • Immutability dát je obrovský prospech, tak, uistite sa, že vaše rozhranie vlastnosti sú všetky readonlyvšetky polia sú readonly T[]a ktoré vlastnosti sú len s komentárom ? alebo | null alebo | undefined ako vhodné miesto jednoducho za predpokladu, že jedným spôsobom, alebo druhej.
  • Takže uistite sa, že používate strictNullChecks vo vašom tsconfig.json alebo tsc voľby! - skutočne, stačí použiť strict vždy!

  • Tiež zvážte zmenu nastavenia JSON DTO od pomocou string zastupovanie Dátum (sú tam nejaké gurantees o časové pásmo?) je natívne čitateľné Unix timestamp (v milisekundách), že spôsob, ako sa môžete vyhnúť problémom s Date.parse celkom:

napríklad:

Výsledok.cs:

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

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

Výsledok.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 );

...tak je to jedno-line prácu.


Vyššie uvedené môžu byť ešte jednoduchšie ako Unix časové sú len celé čísla, ktoré sú priamo porovnateľné, takže new Date() môžete sa vyhnúť vnútri filter, tak ako:

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

Za predpokladu, že máte rozhrania definované ako je tento...

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

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

a chcete filter pre predmety, ktoré sú staršie ako 90 dní (s výnimkou tých, ktoré s č CreatedOn), skúste tento

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)

Strojom Ihrisko Demo

2021-11-24 04:01:43

Pardon moja nevedomosť (a je to dosť veľká diera bane), čo robí ({ CreatedOn, ...item }) => ({ robiť, presne? Nikdy som nevidel šíriť operátora ... používa funkcia parametrov zoznam v rovnakom čase ako objekt-doslovný.
Dai

@Dai výťažky niektorých pomenovaných vlastností (CreatedOn) a udržuje zvyšok v item. V podstate odkaz (obj) => { const { a, b, ...rest } = obj; ...
Phil
-1

kód chýba ) z funkcie filtra

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

Vaša odpoveď nie adresu tsc"s typom chýb.
Dai

Ako je to v súčasnosti napísané, vaša odpoveď je nejasná. Prosím, upravte a pridajte ďalšie podrobnosti, ktoré vám pomôže ostatným pochopiť, ako sa to rieši otázku. Viac informácií môžete nájsť informácie o tom, ako napísať dobrý odpovede v centre pomoci.
Community

V iných jazykoch

Táto stránka je v iných jazykoch

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