joanllenas / ts.data.json

1.7kB JSON decoding library for Typescript
BSD 3-Clause "New" or "Revised" License
205 stars 16 forks source link

Require all keys of an object decoder to be specified #15

Closed tobiwild closed 4 years ago

tobiwild commented 4 years ago

This change requires all keys of an object decoder to be specified, even if they are optional. At the moment this would compile without an error:

    type User = {
      firstname: string;
      lastname: string;
      email?: string;
    };

    const userDecoder = JsonDecoder.object<User>(
      {
        firstname: JsonDecoder.string,
        lastname: JsonDecoder.string
      },
      'User'
    );

I like the idea of adding a new optional property and being forced to be specific about the way it's being decoded. Most of the time I probably want

    email: JsonDecoder.optional(JsonDecoder.string)

If I want it to be ignored, I could use

    email: JsonDecoder.constant<undefined>(undefined),

Does this make sense?

jorroll commented 4 years ago

This functionality already exists in the JsonDecoder.objectStrict decoder. See the docs.

tobiwild commented 4 years ago

I think JsonDecoder.objectStrict is about the JSON data passed in on runtime having only the keys specified by the decoder. But I think my change is not the best idea anyway, because with it you are not able to leave the optional keys out anymore, Object.keys(obj) would always include all the keys.

I think I'm fine with specifying the decoder from the outside like this:

type DecoderObjectAllRequired<a> = { [p in keyof Required<a>]: JsonDecoder.Decoder<a[p]> };
function objectAllRequired<a>(
    decoders: DecoderObjectAllRequired<a>,
    decoderName: string,
    keyMap?: JsonDecoder.DecoderObjectKeyMap<a>
  ): JsonDecoder.Decoder<a> {
    return JsonDecoder.object(decoders, decoderName, keyMap);
  }
const userDecoder = objectAllRequired<User>(
joanllenas commented 4 years ago

@tobiwild Thanks for your contribution! I get your point and it totally makes sense, will merge this, probably write some docs about it, and release a major version (this is a breaking change) during the weekend.

jorroll commented 4 years ago

I think JsonDecoder.objectStrict is about the JSON data passed in on runtime having only the keys specified by the decoder

Ahhh. I misunderstood your goal.

And somewhat tangentially related, I made a custom object decoder for myself which accepts a "removeUndefinedProperties" option. When specified, after an input is successfully decoded any properties which are undefined are deleted from the result. Something similar might provide you with the flexibility you're looking for.

joanllenas commented 4 years ago

Hey @tobiwild , your changes are included in the latest release (v1.0.0).

Thanks!

tobiwild commented 4 years ago

NIce, I'll upgrade my app then, thanks!