Injecting Runtime Dependency in Schema with Context

Hello,

I am trying to build a schema with a runtime dependency. This dependency is a factory that I inject based on what my API is called with.
I have defined it as follows:

export const AddressTypeId: unique symbol = Symbol.for(
  '@spiko/Address'
);
export type AddressTypeId = typeof AddressTypeId;

export interface Address {
  readonly [AddressTypeId]: AddressTypeId;
}

export const isAddress = (a: unknown): a is Address =>
  Predicate.hasProperty(a, AddressTypeId);

export class AddressFactory extends Context.Tag(
  '@services/AddressFactory'
)<
  AddressFactory,
  {
    readonly fromString: (
      s: string
    ) => Effect.Effect<Address, ParseResult.ParseIssue>;
    readonly toString: (
      a: Address
    ) => Effect.Effect<string, ParseResult.ParseIssue>;
  }
>() {}

const AddressSchemaFromSelf = Schema.declare((a) =>
  isAddress(a)
);

export const Address: Schema.Schema<
  Address,
  string,
  AddressFactory
> = Schema.String.pipe(
  Schema.transformOrFail(AddressSchemaFromSelf, {
    encode: (a) =>
      AddressFactory.pipe(Effect.flatMap((f) => f.toString(a))),
    decode: (s) =>
      AddressFactory.pipe(Effect.flatMap((f) => f.fromString(s))),
  })
);


I am then trying to inject a concrete implementation of my factory as follows:

const schema = Address.pipe(
  Effect.provideService(
    AddressFactory,
    new FrenchAddressFactory()
  )
);


But I am getting a type error as I can’t use
pipe
directly on a schema

TL;DR: How would I go about injecting a runtime dependency in a Schema using Context ?
Was this page helpful?