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
What would be an idiomatic way of gracefully handling any potential exceptions?
Effect attempt
Original Code
Consider the code below. Any usage of
LocationIdLocationId , ServiceIdServiceId or DayDay may cause an exception to be thrown when passed to the fetchSchedulesfetchSchedules 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 })),
),
);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,
),
});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,
),
});