Jak filtrovat Strojopis pole založené na možná-undefined datum-jako-řetězec položka objekt, nemovitosti?

0

Otázka

API vrátí výsledek jako objekt s více než tisíc hodnot v následujícím formátu:

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

Chtěl bych filtrovat položky v objektu, které jsou více než 90 dnů, aniž by museli opakovat všechny položky pomocí smyčky for. Jinými slovy já bych chtěl udělat něco jako je to níže, ale to nefunguje.

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

Podle IDE majetku CreatedOn je typu string | undefined takže, to hází error: Argument typ 'string | undefined' nejsou přenosné na parametr typu 'string'. Typ 'undefined' není přiřadit k typu 'string'.

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

Nejlepší odpověď

2

Někde ve vašem projektu, budete mít něco jako toto:

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

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

nebo tento (nebo jejich varianty):

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

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

Nebo to může být type místo interface (jen ujistěte se, že jste nikdy použít class k popisu dat JSON, jako JSON object data nemohou být class instance, protože konstruktor nikdy běží).

Také byste měli být pomocí camelCasene PascalCasepro členské vlastnosti. Takže používat názvy jako createdOn místo CreatedOn na váš vygenerovaný JSON.

Naštěstí nemusíte měnit typů/rozhraní, stačí změnit svůj TypeScript bezpečně zkontrolovat .CreatedOn a že Date.parse nevrátil NaN. Tak jako:

  • Na result.items ?? [] součástí je proto, že váš příspěvek znamená result.items je s možnou hodnotou null nebo možná-undefined.
  • Poznámka: při použití map s =>-styl funkce, které můžete potřebovat zabalit objekt-literály v () takže JS motor nemá interpretovat { a } jako oddělovače bloku.
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;
} );

I když osobně bych to udělal s počáteční filter a map kroky:

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

nebo zjednodušené dále:

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

Ještě lepší řešení:

  • Pokud jste v kontrole toho, jak JSON je generován pak můžete zajistit, že určité (nebo všechny) vlastnosti položky bude vždy být (a tak nikdy undefined nebo null), takže pokud vám nemůže zaručit, že všechny 3 vlastnosti jsou vždy sada (nikdy null nebo undefined), pak aktualizovat svůj typů/rozhraní:

    interface ResultItem {
        readonly name       : string;
        readonly createdOn  : string;
        readonly description: string;
    }
    
    • Poznámka: camelCase vlastnosti.
    • Neměnnost dat , je velkým přínosem, takže ujistěte se, že rozhraní vlastnosti jsou všechny readonlyvšechny pole jsou readonly T[]a které vlastnosti jsou pouze komentovaný s ? nebo | null nebo | undefined jako vhodné místo jednoduše za předpokladu, že jedna cesta nebo jiný.
  • Takže ujistěte se, že používáte strictNullChecks ve vašem tsconfig.json nebo tsc možností! - ve skutečnosti, stačí použít strict vždy!

  • Také zvážit změnu JSON DTO od používání string vyjádření Data (jsou tam nějaké garantuje o časovém pásmu?) být nativně čitelné Unix timestamp (v milisekundách), že způsob, jak se můžete vyhnout problémům s Date.parse zcela:

např.:

Výsledek.cs:

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

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

Výsledek.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 to je single-line práci.


Výše uvedené může být ještě jednodušší, protože Unix časová razítka jsou jen celá čísla, která jsou přímo srovnatelné, takže new Date() se lze vyhnout uvnitř filter, tak jako:

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 předpokladu, že máte rozhraní definované, jako 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, aby filtr pro položky, které jsou starší než 90 dnů (s výjimkou těch s ne CreatedOn), pak zkuste tuto

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)

Strojopis Hřiště Demo

2021-11-24 04:01:43

Omluv mou neznalost (a to je dost velká díra dolu), co dělá ({ CreatedOn, ...item }) => ({ přesně udělat? Nikdy jsem neviděl šíření operátora ... používá se v seznamu parametrů funkce zároveň jako objekt-doslovný.
Dai

@Dai výtažky některé pojmenované vlastnosti (CreatedOn) a udržuje ostatní v item. V podstatě zkratka pro (obj) => { const { a, b, ...rest } = obj; ...
Phil
-1

kód chybí ) filtrační funkce

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še odpověď neřeší tscje typ chyby.
Dai

Tak, jak je napsaná, vaše odpověď je nejasná. Prosím, upravit, přidat další podrobnosti, které ostatním pomohou pochopit, jak se tohle řeší otázku, zeptal se. Můžete si najít více informací o tom, jak psát dobré odpovědi v centru nápovědy.
Community

V jiných jazycích

Tato stránka je v jiných jazycích

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