Unexpected Behavior with `S.Record` Key Refinements in Effect Typescript
With
S.RecordS.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))),
);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))),
);