Challenges in Designing a Domain-Specific Language (DSL) with TypeScript: A Case Study

Hello everyone!)

I've faced some issues while trying to design my DSL:

declare interface Read {
  read(): Effect.Effect<boolean>;
}

declare interface Write extends Read {
  write<A, E, R>(fa: Effect.Effect<A, E, R>): Effect.Effect<void, E, R>;
}

class ReadTx extends Context.Tag("ReadTx")<ReadTx, Read>() {}
class WriteTx extends Context.Tag("WriteTx")<WriteTx, Write>() {}

function prog(): Effect.Effect<[boolean, string], never, ReadTx | WriteTx> {
  const read: Effect.Effect<boolean, never, ReadTx> = Effect.gen(function* () {
    const readTx = yield* ReadTx;

    return yield* readTx.read();
  });
  const write: Effect.Effect<string, never, WriteTx> = Effect.gen(function* () {
    const writeTx = yield* WriteTx;

    const a = yield* writeTx.read();
    const b = yield* writeTx.write(Effect.succeed(a));

    return "done";
  });

  return Effect.gen(function* () {
    const a = yield* read;
    const b = yield* write;

    return [a, b];
  });
}


The type of prog states that it requires both ReadTx and WriteTx which semantically makes no sense since you can both read and write by having WriteTx capability

Is it possible to design it in the way where ReadTx | WriteTx will be composed to WriteTx ?

Thanks
Was this page helpful?