openactive / data-model-validator

The OpenActive data model validator library
MIT License
1 stars 1 forks source link

Couple validation with TypeScript typing, vastly improving code effiency of any TypeScript users of this library #448

Open lukehesluke opened 8 months ago

lukehesluke commented 8 months ago

It would be incredible if, when validating e.g. an Opportunity with Data Model Validator, the function could return the data, typed to use the https://github.com/openactive/models-ts Opportunity type. This way, a user could use the library like this:

const result = typedValidateItem(['ScheduledSession', 'Slot'], maybeASlotOrAScheduledSession);
if (!result.isSuccessful) {
  // throw an error or something
}
if (result.opportunity['@type'] === 'ScheduledSession') {
  // This will be typed as a ScheduledSession from models-ts
  const scheduledSession = result.validated;
  // ... do stuff. 
} else {
  // This will be typed as a Slot from models-ts
  const slot = result.validated;
  // ... do stuff.
}

I think it makes sense to create a new function for this, hence typedValidateItem (though feel free to come up with a better name) — especially as it will need a new type signature and has a new param, and may have some limitations to the more generic validate function. It could be implemented like so:

function typedValidateItem<T extends ScheduledSession['type'] | Slot['type'] | SessionSeries['type'] | /* ...etc... */>(
  expectedTypes: T[],
  item: unknown
): { isSuccessful: true, validated: Extract<ScheduledSession | Slot | SessionSeries | /* ...etc... */, { type: T }> } | { isSuccessful: false, errors: ValidationErrors } {
  if (!_.isPlainObject(item)) {
    // return an error
  }
  const type = item['@type'] || item.type;
  if (!expectedTypes.includes(type)) {
    // return an error
  }
  const validationResult = /* Call Validator's validate function */;
  if (validationResultHasErrors(validationResult)) {
    // return an error
  }
  return { isSuccessful: true, validated: item };
}

Ideally it should support every type that Validator supports validating (which might be all OpenActive types? not sure). To start, it would be great if it could support all of the following crucial types:

Caveats