typebox icon indicating copy to clipboard operation
typebox copied to clipboard

Cannot decode objects with required property which contain a transform

Open sjoerdvanBommel opened this issue 7 months ago • 1 comments

Hi,

I wanted to set a dynamic default value to id properties using Transform, but noticed it throws before decoding because the value does not follow the schema, which is why I'm implementing this :)

Is there a different way to solve this? Am I making a mistake?

  const idWithDefault = Transform(Type.String())
    .Decode((value: string | undefined) => {
      return value || randomUUID();
    })
    .Encode((value: string) => {
      return value || randomUUID();
    });

  const schema = Type.Object({
    document: Type.Object({
      id: idWithDefault,
    }),
    version: Type.String(),
  });

  const decoded = Value.Decode(schema, {
    document: {}, // Errors because id is missing
    version: '1.0.0',
  });

Making it optional does not work either, because then it won't get transformed/decoded when the property does not exist

Thanks in advance!

sjoerdvanBommel avatar Jun 02 '25 13:06 sjoerdvanBommel

Any ideas about this? If this is currently a limitation that you want to add support for, I'm willing to implement it, but I'd need to know the preferred solution.

sjoerdvanBommel avatar Jun 16 '25 09:06 sjoerdvanBommel

@sjoerdvanBommel Hi, sorry for the delay here. I didn't notice this issue until now.

Any ideas about this? If this is currently a limitation that you want to add support for, I'm willing to implement it, but I'd need to know the preferred solution.

This was a limitation, but there has been some big updates released this evening. TypeBox 1.0 provides support default value generation in Codecs (previously Transforms). The following works on TypeBox 1.0. Just be mindful that TypeBox 1.0 will publish to the typebox name on npm moving forward.

Reference Link

import Type from 'typebox'
import Value from 'typebox/value'

function randomUUID(): string {return 'random!!' }

// --------------------------------------------------------
// Transform Renamed to Codec
// --------------------------------------------------------
const idWithDefault = Type.Codec(Type.String({ default: () => randomUUID() })) // add default here to generate
  .Decode((value: string | undefined) => {
    return value || randomUUID();
  })
  .Encode((value: string) => {
    return value || randomUUID();
  });

const schema = Type.Object({
  document: Type.Object({
    id: idWithDefault,
  }),
  version: Type.String(),
});

const decoded = Value.Decode(schema, {
  document: {}, // Errors because id is missing
  version: '1.0.0',
});

console.log(decoded)   // { document: { id: "random!!" }, version: "1.0.0" }

Documentation on TypeBox 1.0 can be found at the link below.

https://sinclairzx81.github.io/typebox/#/

Will close out this issue for now, but if you have any follow up questions, please let me know. All the best! S

sinclairzx81 avatar Sep 09 '25 16:09 sinclairzx81