What version of Effect is running?
4.0.0-rc.117
What steps can reproduce the bug?
All of the annotated code is available in the repo v3-v4-effect-repros:
git clone -b main https://github.com/nikelborm/v3-v4-effect-repros.git
cd v3-v4-effect-repros/effect-v3-behavior/
bun i
# All of the errors are expected
bun tsc
cd ../effect-v4-behavior/
bun i
# 1 expected error is missing, and 1 other unexpected error is present
bun tsc
import { Brand, Schema } from "effect";
type MIDIPortType = "input" | "output";
type Id<TPortType extends MIDIPortType> =
// for distribution
TPortType extends MIDIPortType
? Brand.Branded<string, "MIDIPortId"> & Brand.Brand<TPortType>
: never;
// | (string & Brand.Brand<"MIDIPortId"> & Brand.Brand<"input">)
// | (string & Brand.Brand<"MIDIPortId"> & Brand.Brand<"output">)
export type InputOrOutputMidiPortId = Id<MIDIPortType>;
// Brand.Constructor<InputOrOutputMidiPortId>
export const InputOrOutputMidiPortId = Brand.check<InputOrOutputMidiPortId>(
Schema.isTrimmed(),
Schema.isMinLength(5),
);
// UNEXPECTED: no 'input' | 'output' anywhere:
// Schema.brand<Schema.String, "MIDIPortId">
const InputOrOutputMidiPortIdBrokenSchema = Schema.String.pipe(
Schema.fromBrand("InputOrOutputMidiPortId", InputOrOutputMidiPortId),
);
What is the expected behavior?
The same behavior that I otherwise need to achieve with this workaround:
const Base = Schema.String.pipe(
Schema.fromBrand("MIDIPortId", InputOrOutputMidiPortId),
);
// Deliberately not using Schema.toType(Base) to avoid running the checks twice
const BaseType = Schema.brand("MIDIPortId")(Schema.Unknown as unknown as Schema.String)
return Schema.Union([
BaseType.pipe(Schema.brand("output")),
BaseType.pipe(Schema.brand("input")),
]).pipe(Schema.encodeTo(Base));
What do you see instead?
Essentially, these 2 produce different types:
Option.getOrThrow(InputOrOutputMidiPortIdBrand.option('12345'))
// loses 'input' | 'output'
Schema.decodeSync(InputOrOutputMidiPortIdSchema)('12325')
index.ts:59:38 - error TS1360: Type 'string & Brand<"MIDIPortId">' does not satisfy the expected type 'string & ((Brand<"MIDIPortId"> & Brand<"input">) | (Brand<"MIDIPortId"> & Brand<"output">))'.
Type 'string & Brand<"MIDIPortId">' is not assignable to type 'string & Brand<"MIDIPortId"> & Brand<"output">'.
Type 'string & Brand<"MIDIPortId">' is not assignable to type 'Brand<"output">'.
Types of property '[TypeId]' are incompatible.
Property 'output' is missing in type '{ readonly MIDIPortId: "MIDIPortId"; }' but required in type '{ readonly output: "output"; }'.
59 Schema.decodeSync(IdSchema)("12325") satisfies string &
~~~~~~~~~
Additional information
No response
What version of Effect is running?
4.0.0-rc.117What steps can reproduce the bug?
All of the annotated code is available in the repo
v3-v4-effect-repros:What is the expected behavior?
The same behavior that I otherwise need to achieve with this workaround:
What do you see instead?
Essentially, these 2 produce different types:
Additional information
No response