medikoo / type

Runtime validation and processing of JavaScript types
ISC License
35 stars 4 forks source link

Add coerce for Date #11

Open borracciaBlu opened 4 weeks ago

borracciaBlu commented 4 weeks ago

Hi @medikoo

I've been using type in a new project but discovered that there's no coerce function for date.

Is there a particular reason for this?

If not, would that be possible to have a coerce function for Date please?

Happy to give a hand if you want to

medikoo commented 4 weeks ago

@borracciaBlu coerce is about applying (slightly extended and normalized) JS coercion, which in the language is provided only for primitive types (e.g. in JS into a function that accepts string, you can pass number and it'll be coerced to string for you without any warning).

There are no such coercion mechanisms for object types in JS language, and this library doesn't attempt to break that.

I assume your after some form of Date instance constructors. Are new Date or Date.parse not good enough?

borracciaBlu commented 4 weeks ago

@medikoo I see your point.

The thing i'm working on involve an API from which i should get a string ISO date or null , new Date would be even fine but it does return a Invalid Date and accepts null as valid initial value.

coerce has way more convenient interface, in the sense that you get the thing or null and usually get rid or of null and undefined.

Actually as possible workaround i think i'll glue isValue and isDate after the attempted coercion and that should be it really.

Thanks anyway 🙏

medikoo commented 3 weeks ago

Indeed, ensure for objects, doesn't provide a null fallback for invalid values.

Actually it's an interesting use case, why do you want to silently allow invalid date string?

If you would want to just to permit null or undefined for such value, then you can go as:

const date = isValue(dateString) ? ensureDate(Date.parse(dateString)) : null;
borracciaBlu commented 3 weeks ago

I was thinking something more like:

function (value) {
    if (!isValue(value)) return null;

    const coercedValue = new Date(value);
    if (isDate(coercedValue)) return coercedValue;

    return null;
};

As mentioned new Date should be kind of doing the coercion fine except for null.

[OK] new Date(""); Invalid Date
[OK] new Date([]); Invalid Date
[OK] new Date(undefined); Invalid Date
[NO] new Date(null); Thu Jan 01 1970 10:00:00 GMT+1000 (Australian Eastern Standard Time)
[OK] (new Date("2011-10-05T14:48:00.000Z")).toISOString() '2011-10-05T14:48:00.000Z'

Why do you want to silently allow invalid date string?

Well, not exactly silently actually.

Let's say that it's acceptable to be wrong as far as the app is not broken and the user can still consume the rest of the information.

There is a step of validation and possible errors will be logged and used to provide feedback for BE.

In this particular case the priorities are:

  1. avoid runtime errors
  2. display as much of information as possible despite corrupted data
  3. provide error logs

Just to give you a sense

let resp = callAPI(); // Return a Promise 

resp
    .then(validateAndLogError)

resp
    .then(sanitizeData)
        .then(setData);

// in react then is easy enough to handle null

{
       data  && 
             <p> {data}</p>
}

With something like this having null is convenient.

medikoo commented 3 weeks ago

@borracciaBlu Thanks for clarifications, I think following could be more self-explanatory in this case:

function (value) {
  if (!isValue(value)) return null;
  try {
    return ensureDate(new Date(value));
  } catch (error) {
    // Report invalid input value
    return null;
  }
};