Jak odfiltrować tablica maszynopisu tekstu na podstawie, możliwe, nieokreślony właściwości obiektu "data jak wiersz"?

0

Pytanie

API zwraca wynik w postaci obiektu z ponad tysiącem wartości w następującym formacie:

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

Chciałbym filtrować elementy w obiekcie, w którym ponad 90 dni, bez konieczności powtórzyć wszystkie elementy, za pomocą pętli for. Innymi słowy, chciałbym zrobić coś takiego poniżej, ale to nie działa.

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

Zgodnie z właściwością IDE CreatedOn ma typ string | undefined w ten sposób, to generuje błąd: Argument typu 'string | undefined' nie jest przypisany do typu parametru 'string'. Typ 'undefined' nie może być przypisany do typu 'string'.

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

Najlepsza odpowiedź

2

Gdzieś w projekcie u ciebie będziecoś w stylu tego:

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

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

czy jest to (lub jego warianty):

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

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

Lub to może być type zamiast interface (po prostu upewnij się, że nigdy nie używasz class aby opisać dane JSON, jak JSON object dane nie mogą być class egzemplarz, bo konstruktor nigdy się nie uruchamia).

Ponadto, należy użyć camelCasenie PascalCasedo właściwości elementów. Należy więc stosować nazwy, takie jak createdOn zamiast CreatedOn w generowanych przez was JSON.

Na szczęście, nie trzeba zmieniać typy/interfejsy, po prostu zmień swój tekst, aby bezpiecznie sprawdzić .CreatedOn i co Date.parse nie wrócił NaN. Oto tak:

  • To result.items ?? [] częściowo dlatego, że twój post sugeruje result.items jest nieważne lub może być-undefined.
  • Uwaga podczas korzystania z map z pomocą =>-funkcja stylu, w którą może być owinąć literały obiektowe () w ten sposób silnik JS nie interpretuje { i } jako separatory bloków.
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;
} );

Chociaż osobiście bym zrobił to z początkowej filter i map kroki:

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

lub uproszczone jeszcze więcej:

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

Jeszcze lepsze rozwiązanie:

  • Jeśli możesz kontrolować, jak jest tworzony JSON, można zagwarantować, że niektóre (lub wszystkie) właściwości elementu zawsze będą ustawione (i dlatego nigdy undefined lub null), więc jeśli można zagwarantować, że wszystkie 3 właściwości zawsze ustawione (nigdy null lub undefined), a następnie zaktualizuj swoje typy/interfejsy do tego:

    interface ResultItem {
        readonly name       : string;
        readonly createdOn  : string;
        readonly description: string;
    }
    
    • Należy zwrócić uwagę na camelCase właściwości.
    • Niezmienność danych-ogromną przewagę, więc upewnij się, że wszystkie właściwości interfejsu readonlywszystkie tablice są readonly T[]i że właściwości oznaczone tylko ? lub | null lub | undefined w razie potrzeby, zamiast po prostu przyjąć to, czy tamto.
  • Więc upewnij się, że używasz strictNullChecks W pracy tsconfig.json lub tsc opcje! - w rzeczywistości, po prostu użyj strict zawsze!

  • Także pomyśl o zmianie swojego JSON DTO z użytkowania string widok daty (czy są jakieś gwarancje dotyczące strefy czasowej?) aby być początkowo czytelny datownik Unix (w milisekundach), w ten sposób można uniknąć problemów z Date.parse w całości:

np.:

Wynik. cs:

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

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

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

...w ten sposób,to однострочная praca.


Powyższe można zrobić jeszcze łatwiej, ponieważ tymczasowe Unix-to tylko liczby, które nie są bezpośrednio porównywalne, więc new Date() można uniknąć dostania się do środka filterwłaśnie tak:

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

Zakładając, że masz interfejsy zdefiniowane w ten sposób...

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

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

i chcesz filtrować produkty powyżej 90 dni (za wyjątkiem tych, u których nie ma CreatedOn), wtedy spróbuj

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)

Demonstracja zabaw z машинописным tekstem

2021-11-24 04:01:43

Wybaczcie moją ignorancję (i to dość duży, moja dziura), co sprawia, że ({ CreatedOn, ...item }) => ({ zrobić dokładnie? Nigdy nie widziałem operatora dystrybucji ... stosowany w liście parametrów funkcji jednocześnie z wynikowym znakową.
Dai

@Dai pobiera niektóre nazwane właściwości (CreatedOn) i utrzymuje resztę w item. W zasadzie jest to krótka droga do (obj) => { const { a, b, ...rest } = obj; ...
Phil
-1

kod brakuje ) funkcje 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

Odpowiedź nie dotyczy tscbłędy typu.
Dai

Jak to jest napisane w dzisiejszych czasach, odpowiedź jest niejasna. Proszę, edytuj, aby dodać więcej informacji, które pomogą ludziom zrozumieć, jak to odpowiada na zadane pytanie. Można znaleźć bardziej szczegółowe informacje o tym, jak pisać dobre odpowiedzi, w centrum pomocy.
Community

W innych językach

Ta strona jest w innych językach

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