Comment filtrer un Tapuscrit tableau basé sur peut-être-date non définie en tant que chaîne de caractères de l'élément de propriété de l'objet?

0

La question

L'API retourne le résultat sous la forme d'un objet avec plus d'un millier de valeurs dans le format suivant:

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

Je voudrais filtrer les éléments de l'objet qui sont à plus de 90 jours sans avoir à la parcourir tous les éléments à l'aide de la boucle. En d'autres termes, je voudrais faire quelque chose comme ci-dessous mais cela ne fonctionne pas.

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

Selon l'IDE de la propriété CreatedOn est de type string | undefined donc, il génère l'erreur: Argument de type 'string | undefined' n'est pas assignable à paramètre de type 'string'. Type 'undefined' n'est pas assignable à type de 'string'.

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

La meilleure réponse

2

Quelque part dans votre projet, vous aurez quelque chose comme ceci:

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

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

ou ce (ou une de ses variantes):

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

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

Ou il peut être un type au lieu d'une interface (assurez-vous que vous n'utilisez jamais class pour décrire les données JSON, comme JSON object les données ne peuvent pas être un class exemple parce que le constructeur ne s'exécute).

Aussi, vous devriez être en utilisant camelCase, pas PascalCasepour les propriétés de membre. Donc utiliser des noms comme createdOn au lieu de CreatedOn dans votre générés JSON.

Heureusement, Vous n'avez pas besoin de changer les types/interfaces, il suffit de changer votre Tapuscrit de façon sécuritaire vérifier .CreatedOn et que Date.parse n'a pas de retour NaN. Comme suit:

  • L' result.items ?? [] le cadre est parce que votre poste implique result.items prendre la valeur null ou peut-être-undefined.
  • Remarque lors de l'utilisation de map avec un =>-le style de la fonction que vous pourriez avoir à envelopper l'objet des littéraux dans () ainsi, le moteur JS n'interprète pas le { et } comme délimiteurs 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;
} );

Bien que personnellement je le ferais avec une première filter et map étapes:

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

ou encore simplifié:

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

Une bien meilleure solution:

  • Si vous êtes dans le contrôle de la façon dont le JSON est généré, vous pouvez vous assurer que certaines (ou toutes) les propriétés de l'élément sera toujours ensemble (et donc, ne jamais undefined ou null), donc si vous pouvez garantir que tous les 3 propriétés sont toujours ensemble (jamais null ou undefined) puis mise à jour de vos types de/interfaces à ceci:

    interface ResultItem {
        readonly name       : string;
        readonly createdOn  : string;
        readonly description: string;
    }
    
    • Remarque l' camelCase les propriétés.
    • L'immuabilité de données est un énorme avantage, alors assurez-vous que votre les propriétés de l'interface sont tous readonly, tous les tableaux sont readonly T[]et que les propriétés ne sont annotés avec ? ou | null ou | undefined comme approprié, plutôt que de simplement en supposant que d'une façon ou d'une autre.
  • Donc, assurez-vous d'utiliser strictNullChecks dans votre tsconfig.json ou tsc les options! - en fait, il suffit d'utiliser strict toujours!

  • Aussi, pensez à changer votre JSON DTO de l'utilisation d'un string représentation d'une Date (y at-il garantit à propos de fuseau horaire?) d'être un natif lisible timestamp Unix (en millisecondes), de cette façon, vous pouvez éviter les problèmes avec les Date.parse tout à fait:

par exemple:

Résultat.cs:

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

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

Résultat.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 );

...de cette façon, c'est une seule ligne pour l'emploi.


Le ci-dessus peut être encore plus simple que les timestamps Unix sont tout entiers qui sont directement comparables, de sorte new Date() peut être évitée à l'intérieur de la filter, comme suit:

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

En supposant que vous avez les interfaces définies comme ceci...

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

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

et vous souhaitez filtrer les éléments de plus de 90 jours (à l'exclusion de celles du no CreatedOn), puis essayez ce

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)

Tapuscrit De L'Aire De Jeux Demo

2021-11-24 04:01:43

Pardon pour mon ignorance (et c'est un assez gros trou de mine), ce qui ne ({ CreatedOn, ...item }) => ({ faire, exactement? Je n'ai jamais vu la propagation de l'opérateur ... utilisé dans une fonction de la liste des paramètres en même temps qu'un objet littéral.
Dai

@Dai extraits de certaines propriétés nommées (CreatedOn) et garde le reste dans item. En fait un raccourci pour (obj) => { const { a, b, ...rest } = obj; ...
Phil
-1

le code est manquant ) de la fonction filtre

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

Votre réponse n'a pas d'adresse tscs 'erreurs de type.
Dai

Tel qu'il est actuellement rédigé, votre réponse n'est pas claire. Veuillez modifier pour ajouter des détails supplémentaires qui permettront d'aider les autres à comprendre comment cela répond à la question posée. Vous pouvez trouver plus d'informations sur la façon d'écrire de bonnes réponses dans le centre d'aide.
Community

Dans d'autres langues

Cette page est dans d'autres langues

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