Confirming the legitimacy of ISO-8061 dates using the Decoder method

When it comes to simplicity, using the Decoder approach with io-ts has proven to be effective:

import { isRight } from 'fp-ts/Either';
import * as D from 'io-ts/Decoder';

const thing = D.struct({
  id: D.number,
  createdAt: D.string,
});

export const isValidThing = (candidate: unknown): boolean =>
  isRight(thing.decode(candidate));

However, I am now looking to enhance date validation. I thought I could do something like this:

import { DateFromISOString } from 'io-ts-types/lib/DateFromISOString';

const thing = D.struct({
  id: D.number,
  createdAt: DateFromISOString
});

but it's not as straightforward as I had hoped:

ERROR: src/middleware/validators/event.ts:7:3 - error TS2322: Type 'DateFromISOStringC' is not assignable to type 'Decoder<unknown, Date>'.
  The types returned by 'decode(...)' are incompatible between these types.
    Type 'Validation<Date>' is not assignable to type 'Either<DecodeError, Date>'.
      Type 'Left<Errors>' is not assignable to type 'Either<DecodeError, Date>'.
        Type 'Left<Errors>' is not assignable to type 'Left<DecodeError>'.
          Type 'Errors' is not assignable to type 'DecodeError'.
            Type 'ValidationError[]' is missing the following properties from type 'Concat<DecodeError<string>>': _tag, left, right

    createdAt: DateFromISOString

It seems there was a misunderstanding on my part. Is there a more straightforward way to validate dates using decoders and struct?

Edit: It should be noted that this method does work with the older, non-experimental approach:

import * as t from 'io-ts';
import { DateFromISOString } from 'io-ts-types';

const thing = t.type({
  id: t.number,
  createdAt: DateFromISOString
});

Answer №1

Allow me to provide a response to this question, and if anyone knows of a more efficient method (possibly involving .asDecoder(), which I have yet to master), I am open to learning from that too.

Creating a new Decoder appears to achieve the desired outcome:

const ISODateTime: D.Decoder<unknown, Date> = pipe(
  D.string,
  D.parse((s) => {
    const d = new Date(s);
    return isNaN(d.getTime())
      ? D.failure(s, 'not a valid date format')
      : D.success(d);
  })
);

const thing = D.struct({
  id: D.number,
  createdAt: ISODateTime
});

assert(
  isRight(
    thing.decode({
      id: 1,
      createdAt: '2021-06-26T01:39:06.693Z'
    })
  )
); // true
assert(
  isRight(
    thing.decode({
      id: 1,
      createdAt: 'x1'
    })
  )
); // false

However, it should be noted that this approach does not conclusively confirm that the input string complies with the ISO-8061 format, as Date.parse tends to be quite lenient.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to test multiple store injections withLatestFrom in NgRx Effects?

Within our angular web application, we have implemented NgRx-effects that rely on various data sources within our store. To achieve this, we have adopted the suggested withLatestFrom strategy: withLatestFrom( this.store.pipe(select(...)), this.store ...

Steps to display a modal dialog depending on the category of the label

I'm encountering an issue where clicking on different labels should show corresponding modal dialogs, but it always displays the same modal dialog for both labels ("All Recommendations"). Can anyone offer guidance on how to resolve this problem? Thank ...

Properly incorporating a git+https dependency

I'm facing an issue while trying to utilize a git+https dependency from Github to create a TypeScript library. I've minimized it to a single file for illustration purposes, but it still doesn't work. Interestingly, using a file dependency fu ...

A guide on incorporating "this" keyword within a Mongoose UserSchema method using TypeScript

Currently, I am working on setting up a login API using Mongoose with TypeScript and JSON Web Token. As I am still new to TypeScript, I am facing an issue in the user.model file where I am unable to access any schema property using the "this" method. For e ...

Is it possible to apply two ngClass directives to a single div element in Angular 4?

When I click to start editing, a component is called for the editing process. In this component, I am unable to click on anything and the background turns black, which is okay. However, I would like for each ID that I select to edit to become active with a ...

Experiencing difficulty posting data programmatically, but having success using Swagger

When I try to post data using the following line of code, it does not insert data as expected, even though it works with loopback or swagger. this.http.post(this.Root_url2 + 'busbookings', excelBody) See the complete code below: import { ...

React 16 exhibiting unexpected behavior with class names

I am trying to implement the classnames object into my input field within a react 16 project, completely independent of the webpack tool. const fieldClassName = classnames( formControlStyles.field, 'form-control' ) The 'form-control& ...

Unable to retrieve React state within the callback function

As I work with the following components: const ParentComponent: React.FC = () => { // Setting newType to some value within the code const [newType, setNewType] = useState<any>(undefined); // Enabling addEdge to true in another part o ...

The conflict between ESLint's object curly new line rule and Prettier's multi-line formatting

I'm brand new to the world of prettier, typescript, and eslint. Even though most of the integration is going smoothly, I am facing an issue with multi-line destructuring objects. Prettier Version 1.19.1 Playground link Input: const { ciq, draw ...

Strategies for Creating a Test Suite for RepositoryFactory in Vue.js/Nuxt.js

Summary of RepositoryFactory Implementation An implementation of the RepositoryFactory pattern has been carried out for API connection in a Vue.js/Nuxt.js application. For more details, refer to this article: here hogeRepository.ts import { NuxtAxiosInst ...

An error occurred while trying to load the configuration "next/core-web-vitals" for extension

If you're embarking on a new project using NextJs and TypeScript, chances are you may encounter the following error: Failed to load config "next/core-web-vitals" to extend from. Wondering how to resolve this issue? ...

What sets apart using `: Interface` versus `as Interface` in Typescript?

I'm struggling to find the distinction between two similar lines of code due to uncertainty about what they are called. Consider the scenario where the following interface is defined: interface Person { name: string; age: number; } What exactly ...

Utilize Typescript/Javascript to utilize the Gmail API for sending emails via email

I am trying to send emails from my application using my Gmail account with Ionic. I have followed tutorials from SitePoint and Google Developers. Here is how I'm initializing the client: client_id: gapiKeys.client_id, discoveryDocs: ["https://www.goo ...

Trouble encountered while configuring and executing Electron combined with React, Typescript, and Webpack application

I am currently in the process of migrating my Electron application from ES6 to Typescript. Despite successfully building the dll and main configurations, I encounter a SyntaxError (Unexpected token ...) when attempting to run the application. The project c ...

What is the best way to simulate an observable variable in a unit test?

I am currently in the process of learning how to write unit tests. The following code snippet is part of the coursework that I am studying: #spec.ts ... beforeEach(waitForAsync(() => { const coursesServiceSpy = jasmine.createSpyObj("Cours ...

Incapable of acquiring the classification of the attribute belonging to the

Is it possible to retrieve the type of an object property if that object is stored in a table? const records = [{ prop1: 123, prop2: "fgdgfdg", }, { prop1: 6563, prop2: "dfhvcfgj", }] const getPropertyValues = <ROW extends o ...

Flatten an object in TypeScript

Can the structure of this type be flattened? type MySchema = { fields: { hello: { type: 'Group' fields: { world: { type: 'Group' fields: { yay: { type: 'Boolean' } } } ...

What is the process for enabling keyboard selections in a Material-UI Select component?

Is there a way to make the MUI Select component keyboard accessible by tabbing into it and using the first letter of the option to auto-select without opening the list? I am looking for a feature where pressing the initial letter selects the first item tha ...

Mapping an array in Typescript using Angular to instantiate a class

I have received data from a web API that resembles the structure below. I am looking for guidance on how to properly map the product array into individual Products. My main objective is to convert the eating_time values into JavaScript datetime format. Cu ...

Refreshing an array of objects within a record

I have the following data record stored in Algolia: enterprise_name:"manaslu enterprise", objectID:"14417261",_quotation:[{shamagri_title:"paper ad",price:4000, unit:"per sq inc", description:"5*5", geo_latitude:40, geo_longitude:89, type:"service"} ] I w ...