quarrant/mobx-persist-store

Type issues when using multiple serializable properties

Tartiflettus opened this issue · 11 comments

Hello, first of all, great work on this package, the usage is intuitive, it's customizable, and it's not intrusive: one can use it on mobx stores basically as-is.

When using the package, I stumbled upon a possible issue when writing serializable properties. When using a single serializable property, everything works as intended, but when using 2 or more, the type checker complains about the arguments of the serializers.

Here is an example:

class Store {
  nb = 0;
  str = "0";

  constructor() {
    makeAutoObservable(this);
    makePersistable(this, {
      name: "Store",
      storage: window.localStorage,
      properties: [
        {
          key: "nb",
          serialize(v) { // v is deduced as this["nb" | "str"]
            return `${v}`;
          }
          deserialize(v) { // return type is deduced this["nb" | "str"]
            return parseFloat(v);
          }
        },
        {
          key: "str",
          serialize(v) { // same here for v
            return [v] as const;
          }
          deserialize(v) { // same here for return type
            return v[0];
          }
        }
      ]
    });
  }
}

After following the type declarations, it seems like the issue is that SerializableProperty is generic with 2 arguments: T (type of store), and P (key of store). So once in the properties array, these types are deduced in my example by Store and "nb" | "str".

While the enum deduction is correct when properties is defined as an array of the keys, it leads to this weird behaviour when using serializable properties, where all serializers must handle all used types.

From my perspective, it seems like the required behaviour would be to have each serializable property use it's own P, but after searching for a bit, I don't think that typescript allows this kind of thing :/. For now, I "solved" this by using a separate function that is correctly typed for each use, but degenerates its output type to use any (codesandbox).

What do you think about it, was this indeed not intended, or am I misusing the package?

In all cases have a nice day

Great job! Thank for your issue. I’ll try to fix it on the weekend

@viicky fixed in 1.1.3

Thank you!