Где-то в вашем проекте у вас будет что-то вроде этого:
interface Result {
readonly items: readonly ResultItem[] | null;
}
interface ResultItem {
readonly Name : string;
readonly CreatedOn : string | undefined;
readonly Description: string;
}
или это (или его варианты):
type Result = {
items?: ResultItem[];
}
interface ResultItem {
Name : string;
CreatedOn? : string;
Description: string;
}
Или это может быть type
вместо того, чтобы interface
(просто убедитесь, что вы никогда не используете class
чтобы описать данные JSON, как JSON object
данные не могут быть class
экземпляр, потому что конструктор никогда не запускается).
Кроме того, вы должны использовать camelCase
, не PascalCase
, для свойств элементов. Поэтому используйте такие имена, как createdOn
вместо CreatedOn
в сгенерированном вами JSON.
К счастью, вам не нужно менять типы/интерфейсы, просто измените свой текст, чтобы безопасно проверить .CreatedOn
и что Date.parse
не вернулся NaN
. Вот так:
- То
result.items ?? []
отчасти потому, что ваш пост подразумевает result.items
является недействительным или, может быть-undefined
.
- Примечание при использовании
map
с помощью =>
-функция стиля, в которую может потребоваться обернуть объектные литералы ()
таким образом, движок JS не интерпретирует {
и }
в качестве разделителей блоков.
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;
} );
Хотя лично я бы сделал это с начальной filter
и map
шаги:
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 ) );
или упрощается еще больше:
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 );
Еще лучшее решение:
Если вы контролируете, как создается JSON, вы можете гарантировать, что определенные (или все) свойства элемента всегда будут заданы (и поэтому никогда undefined
или null
), поэтому, если вы можете гарантировать, что все 3 свойства всегда заданы (никогда null
или undefined
) затем обновите свои типы/интерфейсы до этого:
interface ResultItem {
readonly name : string;
readonly createdOn : string;
readonly description: string;
}
- Обратите внимание на
camelCase
свойства.
- Неизменность данных-огромное преимущество, поэтому убедитесь, что все свойства вашего интерфейса
readonly
, все массивы являются readonly T[]
, и что свойства помечены только ?
или | null
или | undefined
по мере необходимости вместо того, чтобы просто предполагать то или иное.
Поэтому убедитесь, что вы используете strictNullChecks
В вашем tsconfig.json
или tsc
варианты! - на самом деле, просто используй strict
всегда!
Также подумайте об изменении вашего JSON DTO с использования string
представление даты (есть ли какие-либо гарантии относительно часового пояса?) чтобы быть изначально читаемой меткой времени Unix (в миллисекундах), таким образом, вы можете избежать проблем с Date.parse
полностью:
напр.:
Результат. cs:
public class ResultItem
{
[JsonProperty( "createdOn" )]
public DateTimeOffset CreatedOn { get; }
[JsonProperty( "createdOnUnix" )]
public Int64 CreatedOnUnix => this.CreatedOn.ToUnixTimeMilliseconds();
}
Результат.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 );
...таким образом,это однострочная работа.
Вышесказанное можно сделать еще проще, поскольку временные метки Unix-это просто целые числа, которые непосредственно сопоставимы, поэтому new Date()
можно избежать попадания внутрь filter
, вот так:
const ninetyDaysAgo = new Date();
ninetyDaysAgo.setDate( ninetyDaysAgo.getDate() - 90 );
const ninetyDaysAgoUnix = ninetyDaysAgo.getTime();
const newResult = items.filter( e => e.createdOnUnix < ninetyDaysAgoUnix );
({ CreatedOn, ...item }) => ({
сделать, точно? Я никогда не видел оператора распространения...
используется в списке параметров функции одновременно с объектным литералом.