Cómo filtrar un Manuscrito de matriz basada en la tal vez-indefinido fecha-como-cadena elemento de la propiedad del objeto?

0

Pregunta

La API devuelve el resultado como un objeto con más de mil de los valores en el formato siguiente:

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

Me gustaría filtrar elementos en el objeto, que son más de 90 días sin tener que recorrer todos los elementos mediante un bucle for. En otras palabras, me gustaría hacer algo como esto más adelante, pero esto no funciona.

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

De acuerdo con el IDE de propiedad CreatedOn es de tipo string | undefined así se produce el error: Argumento de tipo 'string | undefined' no es asignable al parámetro de tipo 'string'. Tipo de 'undefined' no es asignable a tipo de 'string'.

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

Mejor respuesta

2

En alguna parte de tu proyecto, tendrás algo como esto:

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

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

o esta (o variaciones de los mismos):

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

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

O puede ser un type en lugar de una interface (sólo asegúrese de que usted nunca se uso class para describir datos en JSON, como JSON object los datos no puede ser un class instancia porque el constructor no se ejecuta nunca).

También, usted debe utilizar camelCase, no PascalCasepara las propiedades de miembro. Así que el uso de nombres como createdOn en lugar de CreatedOn en su generados JSON.

Afortunadamente, Usted no necesita cambiar el/tipos de interfaces, acaba de cambiar su Manuscrito a la seguridad de verificación .CreatedOn y que Date.parse no volver NaN. Así:

  • El result.items ?? [] parte es porque tu post implica result.items se aceptan valores null o tal vez-undefined.
  • Nota cuando se utiliza map con un =>-función de estilo que usted puede necesitar para envolver objetos literales en () así que el JS motor no interpretar el { y } como delimitadores de bloque.
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;
} );

Aunque personalmente me gustaría hacerlo con una inicial filter y map pasos:

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

o simplificar más:

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

Una solución aún mejor:

  • Si usted está en control de cómo el JSON que se genera, a continuación, usted puede asegurar que algunos (o todos) de las propiedades de elemento siempre (y por lo que nunca undefined o null), así que si usted puede garantizar que todos los 3 propiedades son siempre de ajuste (nunca null o undefined), a continuación, actualizar su/tipos de interfaces para esto:

    interface ResultItem {
        readonly name       : string;
        readonly createdOn  : string;
        readonly description: string;
    }
    
    • Nota la camelCase propiedades.
    • La inmutabilidad de datos es una gran ventaja, así que asegúrese de que su interfaz propiedades son todos readonly, de todas las matrices son readonly T[]y que propiedades sólo están anotados con ? o | null o | undefined como apropiada en lugar de simplemente asumir de una manera o de otra.
  • Así que asegúrese de usar strictNullChecks en su tsconfig.json o tsc opciones! - en realidad, sólo tiene que utilizar strict siempre!

  • También considere la posibilidad de cambiar su JSON DTO del uso de un string representación de una Fecha (¿hay alguna gurantees sobre la zona horaria?) para ser una forma nativa legible timestamp de Unix (en milisegundos), de esa manera usted puede evitar problemas con Date.parse totalmente:

por ejemplo:

Resultado.cs:

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

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

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

...que el camino es de una sola línea de trabajo.


Lo anterior puede ser aún más simple como Unix marcas de tiempo son sólo números enteros que son directamente comparables, por lo que new Date() se puede evitar en el interior de la filter, así:

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

Asumiendo que usted tiene interfaces definidas como este...

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

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

y desea filtrar los elementos que son más de 90 días (excluyendo aquellos que no CreatedOn), a continuación, intente esto

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)

Transcripción De Juegos Demo

2021-11-24 04:01:43

Perdón por mi ignorancia (y es un gran agujero de la mina), lo que hace ({ CreatedOn, ...item }) => ({ qué, exactamente? Nunca he visto a la propagación del operador ... se utiliza en una lista de parámetros de función en el mismo tiempo como un objeto literal.
Dai

@Dai extractos de algunas de las propiedades con nombre (CreatedOn) y se guarda el resto en item. Básicamente un acceso directo para (obj) => { const { a, b, ...rest } = obj; ...
Phil
-1

código falta ) de la función de filtro

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

Su respuesta no la dirección tsc's tipo de errores.
Dai

Como está escrito, su respuesta no está clara. Por favor editar para agregar detalles adicionales que ayudarán a otros a entender cómo esto se refiere a la pregunta. Usted puede encontrar más información sobre cómo escribir buenas respuestas en el centro de ayuda.
Community

En otros idiomas

Esta página está en otros idiomas

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