47ng / nuqs

Type-safe search params state manager for React frameworks - Like useState, but stored in the URL query string.
https://nuqs.47ng.com
MIT License
4.91k stars 105 forks source link

TypeError: v.toISOString is not a function #692

Closed bryanjtc closed 1 month ago

bryanjtc commented 1 month ago

Context

What's your version of nuqs?

2.0.0

What framework are you using?

Which version of your framework are you using?

6.27.0

Description

I used the createSerializer utility where a param is using the parseAsIsoDateTime parser and I have this error. The value is an iso 8601 string. I expected it to not throw an error. The temporary fix is to convert the iso 8601 string to a Date object first and then use the value in the serializer.

chunk-FFJRS6S6.js?v=7de39fa0:7581 Uncaught TypeError: v.toISOString is not a function
    at Object.serialize (nuqs.js?v=7de39fa0:209:23)
    at serialize (nuqs.js?v=7de39fa0:314:32)

Here is the code that throws the error

var parseAsIsoDateTime = createParser({
  parse: (v) => {
    const date = new Date(v);
    if (Number.isNaN(date.valueOf())) {
      return null;
    }
    return date;
  },
  serialize: (v) => v.toISOString()
});

Reproduction

  1. Create a serializer
  2. Add a param with the parseAsIsoDateTime parser
  3. Add an iso 8601 string value in the serialize function
franky47 commented 1 month ago

The value is an iso 8601 string

parseAsIsoDateTime works with Date objects, not strings. TypeScript should give you an error when trying to pass a string to the serialize function.

Here's a variant that might work for keeping it a string (and only validating the format):

const parseAsIsoDateString = createParser({
  parse: (v) => {
    const date = new Date(v);
    if (Number.isNaN(date.valueOf())) {
      return null;
    }
    return v;
  }
});
bryanjtc commented 1 month ago

I had i few type errors when using your variant. Here is what I used

export const parseAsIsoDateString = createParser({
  parse: (v) => {
    const date = new Date(v);
    if (Number.isNaN(date.valueOf())) {
      return null;
    }
    return date;
  },
  serialize: (value) => {
    const date = new Date(value);
    return date.toISOString();
  }
});

Comments:

1. Since the createParser helper uses the type of the return value of the parse function, I returned the date variable.
2. Serialize is required, so i just converted the string to a Date and then back to iso string
franky47 commented 1 month ago

That would work. Do you not have an error when trying to serialize a string though? Because it should only accept a Date object.

TypeScript should give you an error when trying to pass a string to the serialize function.

bryanjtc commented 1 month ago

That would work. Do you not have an error when trying to serialize a string though? Because it should only accept a Date object.

TypeScript should give you an error when trying to pass a string to the serialize function.

No. I converted the string (value) to a Date object first