Improving TypeScript Schema Design for API Validation and Transformation

Perhaps a newbie question but I feel that my approach using Schemas could be improved. (I have a working solution but doesn't feel elegant)

I want to describe my domain types and my api type validations with Schemas the simplest, least boilerplate'd way possible.

My domain is for example:
typescript 
const Region = Schema.Struct({
  id: Schema.NonEmptyTrimmedString
});

const Country = Schema.Struct({
  id: Schema.NonEmptyTrimmedString,
  region: Schema.optionalWith(Region, {as: "Option"})
});

const City = Schema.Struct({
  id: Schema.NonEmptyTrimmedString,
  country: Schema.optionalWith(Country, {as: "Option"})
});


..these are loaded via an API as three separate calls so I create 3 Schemas that explicitly validate the shape of the payloads:
 typescript
const RegionDTO = Schema.Struct({
  id: Schema.NonEmptyTrimmedString
});

const CountryDTO = 
Schema.Struct({
  id: Schema.NonEmptyTrimmedString,
  region: Schema.optionalWith(Schema.NonEmptyString) // this is the id of the Region
});
...etc...same logic goes for city

then I define transformations (in 3 layers that are dependent on each other) for each, eg:
typescript 
const dto2City = Schema.transformOrFail(CityDTO, City, {strict: true, decode:(dto...)=>..., encode(city..)=>...}) 


My issue is that I think it would be more elegant if I could parse the optional IDs to Options already at the DTO Schemas so I can deal with them in the decode(..) and encode(..) functions easier. Now I have to convert between Options and <A | undefined> types a lot, especially in the City decoder where the country's region has to be mapped from Option to <CityType | undefined> because the Inferred type of the City schema is not an Option but an optional <CityType | undefined>.

would appreciate some help...
Was this page helpful?