Bir TypeScript dizisini maybe-undefined date-as-string item object özelliğine göre nasıl filtreleyebilirim?

0

Soru

API, sonucu aşağıdaki biçimde binden fazla değere sahip bir nesne olarak döndürür:

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

For döngüsünü kullanarak tüm öğeleri yinelemek zorunda kalmadan 90 günden daha eski olan nesnedeki öğeleri filtrelemek istiyorum. Başka bir deyişle, aşağıda böyle bir şey yapmak istiyorum ama bu işe yaramıyor.

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

IDE özelliğine göre CreatedOn yazın string | undefined bu yüzden hatayı atar: Tür argümanı 'string | undefined' tür parametresine atanamaz 'string'. Tip 'undefined' türe atanamaz 'string'.

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

En iyi cevabı

2

Projenizin bir yerinde şöyle bir şey olacak:

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

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

veya bu (veya bunların varyasyonları):

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

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

Ya olabilir type yerine bir interface (sadece asla kullanmadığınızdan emin olun class JSON verilerini JSON olarak tanımlamak için object veri bir olamaz class yapıcı hiçbir zaman çalışmadığı için örnek).

Ayrıca kullandığınız camelCase, değil PascalCase. üye özellikleri için. Bu yüzden aşağıdaki gibi isimler kullanın createdOn yerine CreatedOn oluşturulan Json'unuzda.

Neyse ki Türleri/arayüzleri değiştirmeniz gerekmez, sadece güvenli bir şekilde kontrol etmek için typescript'inizi değiştirin .CreatedOn ve bu Date.parse geri dönmedi NaN. Öyle gibi:

  • Bu result.items ?? [] bunun bir kısmı, gönderinizin ima ettiği içindir result.items geçersiz veya belki-undefined.
  • Kullanırken dikkat edin map bir ile =>- nesne değişmezlerini kaydırmanız gerekebilecek stil işlevi () yani JS motoru yorumlamıyor { ve } blok sınırlayıcı olarak.
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;
} );

Şahsen bunu bir başlangıç ile yapardım filter ve map adımlar:

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

veya daha da basitleştirildi:

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

Daha da iyi bir çözüm:

  • Json'un nasıl oluşturulduğunu kontrol ediyorsanız, belirli (veya tüm) öğe özelliklerinin her zaman ayarlanacağından emin olabilirsiniz (ve böylece hiçbir zaman undefined veya nullbu nedenle, tüm 3 özelliğin her zaman ayarlandığını garanti edebilirseniz (asla null veya undefined) daha sonra türlerinizi/arayüzlerinizi buna güncelleyin:

    interface ResultItem {
        readonly name       : string;
        readonly createdOn  : string;
        readonly description: string;
    }
    
    • Not camelCase özellikleri.
    • Verilerin değişmezliği büyük bir avantajdır, bu nedenle arayüz özelliklerinizin hepsinin olduğundan emin olun readonly, tüm diziler şunlardır readonly T[] ve bu özellikler yalnızca açıklamalı ? veya | null veya | undefined sadece bir şekilde veya başka bir şekilde varsaymak yerine uygun.
  • Bu yüzden kullandığınızdan emin olun strictNullChecks senin içinde tsconfig.json veya tsc seçenekler! - aslında, sadece kullan strict her zaman!

  • Ayrıca JSON dto'nuzu a kullanmaktan değiştirmeyi düşünün string bir Tarihin Temsili (saat dilimi hakkında herhangi bir garanti var mı?) yerel olarak okunabilir bir Unix zaman damgası (milisaniye cinsinden) olmak için, bu şekilde şunlarla ilgili sorunları önleyebilirsiniz: Date.parse tamamen:

örneğin:

Sonuç.cs:

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

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

Sonuç.TH:

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

...böylece tek satırlık bir iş olur.


Unix zaman damgaları sadece doğrudan karşılaştırılabilir tamsayılar olduğundan, yukarıdakiler daha da basit hale getirilebilir, bu nedenle new Date() içinde önlenebilir filter böyle:

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

Bu şekilde tanımlanmış arayüzleriniz olduğunu varsayarsak...

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

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

ve 90 günden daha eski olan öğeleri filtrelemek istiyorsunuz (olmayanlar hariç CreatedOn), o zaman bu deneyin

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)

TypeScript Oyun Alanı Demosu

2021-11-24 04:01:43

Cehaletimi affet (ve bu benim oldukça büyük bir deliğim), ne yapar ({ CreatedOn, ...item }) => ({ aynen öyle mi? Yayılma operatörünü hiç görmedim. ... bir nesne değişmeziyle aynı anda bir işlev parametre listesinde kullanılır.
Dai

@Dai bazı adlandırılmış özellikleri ayıklar (CreatedOn) ve gerisini içeride tutar item. Temel olarak bir kısayol (obj) => { const { a, b, ...rest } = obj; ...
Phil
-1

filtre işlevinin kodu eksik )

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

Cevabınız cevap vermiyor tsctip hataları.
Dai

Şu anda yazıldığı gibi, cevabınız belirsizdir. Lütfen başkalarının sorulan soruyu nasıl ele aldığını anlamalarına yardımcı olacak ek ayrıntılar eklemek için düzenleyin. İyi yanıtların nasıl yazılacağı hakkında daha fazla bilgiyi yardım merkezi'nde bulabilirsiniz.
Community

Diğer dillerde

Bu sayfa diğer dillerde

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