Unexpected Behavior with `S.Record` Key Refinements in Effect Typescript

With S.Record are refinements on keys supposed to act as filters oppose to failing to decode?

import { Cause, Effect, flow, Schema as S } from 'effect';

Effect.runPromise(
  Effect.gen(function* (_) {
    const vector = { '@foo': '@bar' };
    const NoAt = S.String.pipe(S.pattern(/^[^@]+$/));

    // no '@' in keys
    const res1 = yield* S.decode(S.Record({ key: NoAt, value: S.String }))(vector);
    console.log(res1); // prints {}, expected to fail?

    // attempt 2 with struct
    const res2 = yield* S.decode(S.Struct({}, { key: NoAt, value: S.String }))(vector);
    console.log(res2); // prints {}, expected to fail?

    // no pattern
    const res3 = yield* S.decode(S.Record({ key: S.String, value: S.String }))(vector);
    console.log(res3); // prints { '@foo': 'bar' }, expected to pass

    // attempt 4 with a different refinement
    const res4 = yield* S.decode(S.Record({ key: S.String.pipe(S.maxLength(2)), value: S.String }))(vector);
    console.log(res4); // prints {}, expected to fail?

    // sanitfy check that refinements on values cause failures
    const res5 = yield* S.decode(S.Record({ key: S.String, value: NoAt }))(vector);
    console.log(res5); // successfully fails
  }).pipe(Effect.catchAllCause(flow(Cause.pretty, Effect.logFatal))),
);
Was this page helpful?