Arbitrary.schema: no generation override for a struct's cross-field filter, and lookahead patterns are skipped quietly

Aperta
#10,479 0 commenti 0 reazioni 1 assegnatario Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@effect-bot ci sta già lavorando.

Dal 9/11/2026.

Valutazione

Questa issue non è ancora stata valutata.

Descrizione

Version: effect 4.1.1 (effect/Arbitrary; @effect/vitest 4.1.1 it.prop calls Arbitrary.schema on Schema inputs, so it fails the same way).

Two gaps in Arbitrary.schema. Both end in SampleError after 2001 discards.

1. A cross-field filter on a struct has no generation override
import {Arbitrary, Effect, Schema} from "effect";

const Dead = Schema.Struct({
	tries: Schema.Int.check(Schema.isGreaterThanOrEqualTo(1)),
	errors: Schema.Array(Schema.String).check(Schema.isMaxLength(32)),
}).check(Schema.makeFilter((v) => v.errors.length === v.tries || "one error per try"));

await Effect.runPromise(Arbitrary.sampleEffect(Arbitrary.schema(Dead), {count: 200, seed: 119120}));
// SampleError {generated: 29, discards: 2001}

arbitraryConstraint cannot say "these two fields agree", and toCodecArbitrary is read only on declarations. In v3, an arbitrary annotation on any schema could replace generation. Could a filter, or any node, take a generation override (an Arbitrary, or a toCodecArbitrary-style link)? Today the workaround is to keep a hand-built Arbitrary next to the schema and pass that to it.prop, so the schema and its generator can drift apart.

2. isPattern with a lookahead is skipped quietly
const TraceId = Schema.String.check(Schema.isPattern(/^(?!0{32})[0-9a-f]{32}$/));
await Effect.runPromise(Arbitrary.sampleEffect(Arbitrary.schema(TraceId), {count: 200, seed: 119120}));
// SampleError {generated: 0, discards: 2001}

The pattern is not compiled for generation, so the generator falls back to random strings and the filter discards all of them. Two asks, either helps: support lookahead (or at least a leading negative lookahead), or throw at derivation with an error that names the pattern it could not compile, instead of the discard error at sample time.

Workaround in use: the same set without a lookahead, isPattern(/^[0-9a-f]{32}$/) plus a filter t !== "0".repeat(32), generates 500 of 500 valid values.

Lingua principale
TypeScript
Stelle
16.7k
Fork
808
Merge medio
17h 9m
PR unite (30g)
825

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Effect-TS/effect

Tutte le issue di Effect-TS/effect

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.