Skip to content

Should decoders match their decoded type exactly, or should there be multiple valid decoders for a type? #23

Open
@mulias

Description

@mulias

Recently I've been exploring ways to require that the optional decoder be used for fields that are optional. From that process I've realized that I need to make a number of subtle design decisions related to how loosely or strictly a decoder needs to match a type. On the one hand, we should leverage typescript to help us write decoders that are as accurate as possible. On the other hand, I don't want the rules/guidelines around writing decoders to get too complicated, and I also don't want to be overbearing and prevent the user from writing the exact decoder they intend to.

With all that in mind, I've got a few examples of situations where I could change the library to more strictly fit decoders to types. Please respond with feedback to the three questions, plus any other concerns or observations you've got.

  1. Here are four decoders for the interface AB. All four decoders are valid and will compile without errors. In an ideal world, which of these decoders would you want to be valid, and which ones should produce an error?
interface AB {
  a: string;
  b?: number;
}

const decoderAB1 = object({
  a: string(),
  b: optional(number())
});

const decoderAB2 = object({
  a: string(),
  b: number()
});

const decoderAB3 = object({
  a: string(),
  b: union(number(), constant(undefined))
});

const decoderAB4 = object({
  a: string()
});
  1. Ditto for CD. All four decoders are valid, but as a library user which ones would you want to be valid?
interface CD {
  c: string;
  d: number | undefined;
}

const decoderCD1 = object({
  c: string(),
  d: optional(number())
});

const decoderCD2 = object({
  c: string(),
  d: constant(undefined)
});

const decoderCD3 = object({
  c: string(),
  d: union(number(), constant(undefined))
});

const decoderCD4 = object({
  c: string()
});
  1. Ditto for E.
interface E {
  e: string | number;
}

const decoderE1 = object({
  e: union(string(), number())
});

const decoderE2 = object({
  e: string()
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions