tywalch/electrodb

"Property x is missing in type" Typescript error when using setters to set properties that are in composite keys

Closed this issue · 2 comments

Describe the bug
Given this minimal example gist that reproduces this error, I would expect that I should be able to create new items and autogenerate the id at the entity level.

Instead, I get a Typescript error:

image

This makes sense -- the id is required in order to create an index and I do notCo encounter Typescript errors like this on attributes that are not part of the Composite Attributes.

But it seems to make sense to me that I should be able to generate the id using an Attribute Setter, since downstream logic shouldn't concern itself with that.

The workaround, of course, is to do something like the following:

 id: {
    type: "string",
    set: (id) => {
            if (!id) {
              return randomUUID();
            }
          },
          required: true,
          readOnly: true,
     }        

And then manually pass in an id when creating a new entity:

  const data = {
    name: "blah",
    id: randomUUID()
  };

  const item = await entity.create(data).go();

Or just not use an attribute setter for the id property. But that seems inelegant; I think ElectroDB Entities should be able to handle setting the id in a case like this, rather than relying on downstream logic. Since it's readOnly, I'm not worried about the warning in the readme about using attribute setters on Composite Attributes.

I'm not sure what the best solution, if any, is here, but happy to chip in if needed.

ElectroDB Version
2.3.3

ElectroDB Playground Link
Example

Entity/Service Definitions
Include your entity model (or a model that sufficiently recreates your issue) to help troubleshoot.

    {
      model: {
        entity: "device",
        version: "1",
        service: "DeviceService",
      },
      attributes: {
        id: {
          type: "string",
          set: () => randomUUID(),
          required: true,
          readOnly: true
        },
        name: {
          type: "string",
        },
      },
      indexes: {
        id: {
          pk: {
            field: "pk",
            composite: ["id"],
          },
        },
      },
    }

Expected behavior
I expect to be able to delegate the setting of the id attribute to the ElectroDB entity, even though it's part of my primary key.

Errors

error TS2345: Argument of type '{ name: string; }' is not assignable to parameter of type 'PutItem<string, string, string, { model: { entity: string; version: string; service: string; }; attributes: { id: { type: "string"; set: (id: string) => string; required: true; readOnly: true; }; name: { type: "string"; }; }; indexes: { ...; }; }>'.
  Property 'id' is missing in type '{ name: string; }' but required in type 'Pick<CreatedItem<string, string, string, { model: { entity: string; version: string; service: string; }; attributes: { id: { type: "string"; set: (id: string) => string; required: true; readOnly: true; }; name: { ...; }; }; indexes: { ...; }; }, { ...; }>, "id">'.

Ah @tywalch - that makes sense. I thought I was doing something wrong. Marking this as closed for others to reference if they run into an issue like this in the future. I might be interested in helping add these kinds of examples to documentation / examples as well as I really enjoy this library but it was a bit tricky to learn the ropes. I'll be in touch about that soon! Thank you so much! <3