Effect CommunityEC
Effect Community3y ago
5 replies
erikshestopal

Handling Exceptions with Branded Types and Control Flow

Hey all, a quick question about branded types as well as general control flow.

Consider the code below. Any usage of LocationId , ServiceId or Day may cause an exception to be thrown when passed to the fetchSchedules function.
What would be an idiomatic way of gracefully handling any potential exceptions?

Effect attempt

Effect.all([
  Effect.try(() => LocationId(location.id)),
  Effect.try(() => ServiceId(input.serviceId)),
  Effect.try(() =>
    Option.fromNullable(requestedAppointmentDate.weekdayLong).pipe(
      Option.map((day) => Day(day.toLowerCase())),
      Option.getOrThrow,
    ),
  ),
]).pipe(
  Effect.flatMap(([locationId, serviceId, day]) =>
    Effect.tryPromise(async () => await fetchSchedules({ locationId, serviceId, day })),
  ),
);


Original Code
export const LocationId = S.string.pipe(
  S.trim,
  S.startsWith('loc_'),
  S.brand(Symbol.for('LocationId')),
);

export const ServiceId = S.string.pipe(
  S.trim,
  S.startsWith('ser_'),
  S.brand(Symbol.for('ServiceId')),
);

const DAYS = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday'];
export const Day = S.string.pipe(
  S.filter((value) => DAYS.includes(value.toLowerCase()), {
    message: (value) => `${value} is not a valid day`,
    identifier: 'Day',
  }),
  S.brand(Symbol.for('Day')),
);


const requestedAppointmentDate = DateTime.fromISO(input.date, {
  zone: location.timeZone,
});

const schedule = await fetchSchedules({
  locationId: LocationId(location.id),
  serviceId: ServiceId(input.serviceId),
  day: Option.fromNullable(requestedAppointmentDate.weekdayLong).pipe(
    Option.map((day) => Day(day.toLowerCase())),
    Option.getOrThrow,
  ),
});
Was this page helpful?