diff --git a/.changeset/weak-tables-matter.md b/.changeset/weak-tables-matter.md new file mode 100644 index 00000000000..876eed316c8 --- /dev/null +++ b/.changeset/weak-tables-matter.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +Add typeConstructor annotation for Schema diff --git a/packages/ai/ai/src/Prompt.ts b/packages/ai/ai/src/Prompt.ts index d715364055e..055e4fd7a20 100644 --- a/packages/ai/ai/src/Prompt.ts +++ b/packages/ai/ai/src/Prompt.ts @@ -1333,6 +1333,7 @@ export interface PromptEncoded { export class PromptFromSelf extends Schema.declare( (u) => isPrompt(u), { + typeConstructor: { _tag: "effect/ai/Prompt" }, identifier: "PromptFromSelf", description: "a Prompt instance", arbitrary: (): Arbitrary.LazyArbitrary => (fc) => diff --git a/packages/cluster/src/Envelope.ts b/packages/cluster/src/Envelope.ts index 47121302dac..fc7f18ffbfc 100644 --- a/packages/cluster/src/Envelope.ts +++ b/packages/cluster/src/Envelope.ts @@ -204,6 +204,7 @@ export const EnvelopeFromSelf: Schema.Schema< Envelope.Any, Envelope.Any > = Schema.declare(isEnvelope, { + typeConstructor: { _tag: "effect/cluster/Envelope" }, identifier: "Envelope" }) @@ -215,6 +216,7 @@ export const RequestFromSelf: Schema.Schema< Request.Any, Request.Any > = Schema.declare((u): u is Request.Any => isEnvelope(u) && u._tag === "Request", { + typeConstructor: { _tag: "effect/cluster/Envelope.Request" }, identifier: "Envelope" }) diff --git a/packages/cluster/src/Reply.ts b/packages/cluster/src/Reply.ts index 77ec5bab264..5d56bde9ca3 100644 --- a/packages/cluster/src/Reply.ts +++ b/packages/cluster/src/Reply.ts @@ -192,8 +192,11 @@ export class Chunk extends Data.TaggedClass("Chunk")<{ /** * @since 1.0.0 */ - static readonly schemaFromSelf: Schema.Schema> = Schema.declare((u): u is Chunk => - isReply(u) && u._tag === "Chunk" + static readonly schemaFromSelf: Schema.Schema> = Schema.declare( + (u): u is Chunk => isReply(u) && u._tag === "Chunk", + { + typeConstructor: { _tag: "effect/cluster/Reply.Chunk" } + } ) /** diff --git a/packages/effect/src/Schema.ts b/packages/effect/src/Schema.ts index bb8739fb826..885e36ca166 100644 --- a/packages/effect/src/Schema.ts +++ b/packages/effect/src/Schema.ts @@ -4148,6 +4148,7 @@ export declare namespace Annotations { * @since 3.10.0 */ export interface Schema = readonly []> extends Doc { + readonly typeConstructor?: AST.TypeConstructorAnnotation readonly identifier?: AST.IdentifierAnnotation readonly message?: AST.MessageAnnotation readonly schemaId?: AST.SchemaIdAnnotation @@ -4918,6 +4919,7 @@ export class ULID extends String$.pipe( * @since 3.11.0 */ export class URLFromSelf extends instanceOf(URL, { + typeConstructor: { _tag: "URL" }, identifier: "URLFromSelf", arbitrary: (): LazyArbitrary => (fc) => fc.webUrl().map((s) => new URL(s)), pretty: () => (url) => url.toString() @@ -5850,6 +5852,7 @@ export const RedactedFromSelf = (value: Value): Redact encode: (value) => redactedParse(ParseResult.encodeUnknown(value)) }, { + typeConstructor: { _tag: "effect/Redacted" }, description: "Redacted()", pretty: () => () => "Redacted()", arbitrary: redactedArbitrary, @@ -5891,6 +5894,7 @@ export function Redacted(value: Value): Redacted => String, arbitrary: (): LazyArbitrary => (fc) => @@ -6194,6 +6198,7 @@ export const betweenDuration = ( export class Uint8ArrayFromSelf extends declare( Predicate.isUint8Array, { + typeConstructor: { _tag: "Uint8Array" }, identifier: "Uint8ArrayFromSelf", pretty: (): pretty_.Pretty => (u8arr) => `new Uint8Array(${JSON.stringify(Array.from(u8arr))})`, arbitrary: (): LazyArbitrary => (fc) => fc.uint8Array(), @@ -6781,6 +6786,7 @@ export type DateFromSelfSchemaId = typeof DateFromSelfSchemaId export class DateFromSelf extends declare( Predicate.isDate, { + typeConstructor: { _tag: "Date" }, identifier: "DateFromSelf", schemaId: DateFromSelfSchemaId, [DateFromSelfSchemaId]: { noInvalidDate: false }, @@ -6874,6 +6880,7 @@ export class DateFromNumber extends transform( export class DateTimeUtcFromSelf extends declare( (u) => dateTime.isDateTime(u) && dateTime.isUtc(u), { + typeConstructor: { _tag: "effect/DateTime.Utc" }, identifier: "DateTimeUtcFromSelf", description: "a DateTime.Utc instance", pretty: (): pretty_.Pretty => (dateTime) => dateTime.toString(), @@ -6950,6 +6957,7 @@ const timeZoneOffsetArbitrary = (): LazyArbitrary => ( export class TimeZoneOffsetFromSelf extends declare( dateTime.isTimeZoneOffset, { + typeConstructor: { _tag: "effect/DateTime.TimeZone.Offset" }, identifier: "TimeZoneOffsetFromSelf", description: "a TimeZone.Offset instance", pretty: (): pretty_.Pretty => (zone) => zone.toString(), @@ -6985,6 +6993,7 @@ const timeZoneNamedArbitrary = (): LazyArbitrary => (fc export class TimeZoneNamedFromSelf extends declare( dateTime.isTimeZoneNamed, { + typeConstructor: { _tag: "effect/DateTime.TimeZone.Named" }, identifier: "TimeZoneNamedFromSelf", description: "a TimeZone.Named instance", pretty: (): pretty_.Pretty => (zone) => zone.toString(), @@ -7054,6 +7063,7 @@ const timeZoneArbitrary: LazyArbitrary = (fc) => export class DateTimeZonedFromSelf extends declare( (u) => dateTime.isDateTime(u) && dateTime.isZoned(u), { + typeConstructor: { _tag: "effect/DateTime.Zoned" }, identifier: "DateTimeZonedFromSelf", description: "a DateTime.Zoned instance", pretty: (): pretty_.Pretty => (dateTime) => dateTime.toString(), @@ -7169,6 +7179,7 @@ const OptionFromSelf_ = (value: Value): OptionFromSelf encode: (value) => optionParse(ParseResult.encodeUnknown(value)) }, { + typeConstructor: { _tag: "effect/Option" }, pretty: optionPretty, arbitrary: optionArbitrary, equivalence: option_.getEquivalence @@ -7427,6 +7438,7 @@ export const EitherFromSelf = ({ lef encode: (right, left) => eitherParse(ParseResult.encodeUnknown(right), ParseResult.encodeUnknown(left)) }, { + typeConstructor: { _tag: "effect/Either" }, description: `Either<${format(right)}, ${format(left)}>`, pretty: eitherPretty, arbitrary: eitherArbitrary, @@ -7615,6 +7627,7 @@ const mapFromSelf_ = ( encode: (Key, Value) => readonlyMapParse(ParseResult.encodeUnknown(Array$(Tuple(Key, Value)))) }, { + typeConstructor: { _tag: "ReadonlyMap" }, description, pretty: readonlyMapPretty, arbitrary: mapArbitrary, @@ -7797,6 +7810,7 @@ const setFromSelf_ = (value: Value, description: strin encode: (item) => readonlySetParse(ParseResult.encodeUnknown(Array$(item))) }, { + typeConstructor: { _tag: "ReadonlySet" }, description, pretty: readonlySetPretty, arbitrary: setArbitrary, @@ -7898,6 +7912,7 @@ const bigDecimalArbitrary = (): LazyArbitrary => (fc) => export class BigDecimalFromSelf extends declare( bigDecimal_.isBigDecimal, { + typeConstructor: { _tag: "effect/BigDecimal" }, identifier: "BigDecimalFromSelf", pretty: bigDecimalPretty, arbitrary: bigDecimalArbitrary, @@ -8267,6 +8282,7 @@ export const ChunkFromSelf = (value: Value): ChunkFrom encode: (item) => chunkParse(ParseResult.encodeUnknown(Array$(item))) }, { + typeConstructor: { _tag: "effect/Chunk" }, description: `Chunk<${format(value)}>`, pretty: chunkPretty, arbitrary: chunkArbitrary, @@ -8338,6 +8354,7 @@ export const NonEmptyChunkFromSelf = (value: Value): N encode: (item) => nonEmptyChunkParse(ParseResult.encodeUnknown(NonEmptyArray(item))) }, { + typeConstructor: { _tag: "effect/Chunk.NonEmptyChunk" }, description: `NonEmptyChunk<${format(value)}>`, pretty: nonEmptyChunkPretty, arbitrary: nonEmptyChunkArbitrary, @@ -9194,6 +9211,7 @@ const fiberIdPretty: pretty_.Pretty = (fiberId) => { export class FiberIdFromSelf extends declare( fiberId_.isFiberId, { + typeConstructor: { _tag: "effect/FiberId" }, identifier: "FiberIdFromSelf", pretty: () => fiberIdPretty, arbitrary: () => fiberIdArbitrary @@ -9409,6 +9427,7 @@ export const CauseFromSelf = ({ defe encode: (error, defect) => causeParse(ParseResult.encodeUnknown(causeEncoded(error, defect))) }, { + typeConstructor: { _tag: "effect/Cause" }, title: `Cause<${error.ast}>`, pretty: causePretty, arbitrary: causeArbitrary @@ -9659,6 +9678,7 @@ export const ExitFromSelf = `, pretty: exitPretty, arbitrary: exitArbitrary @@ -9771,6 +9791,7 @@ export const HashSetFromSelf = ( encode: (item) => hashSetParse(ParseResult.encodeUnknown(Array$(item))) }, { + typeConstructor: { _tag: "effect/HashSet" }, description: `HashSet<${format(value)}>`, pretty: hashSetPretty, arbitrary: hashSetArbitrary, @@ -9870,6 +9891,7 @@ export const HashMapFromSelf = ({ ke encode: (key, value) => hashMapParse(ParseResult.encodeUnknown(Array$(Tuple(key, value)))) }, { + typeConstructor: { _tag: "effect/HashMap" }, description: `HashMap<${format(key)}, ${format(value)}>`, pretty: hashMapPretty, arbitrary: hashMapArbitrary, @@ -9956,6 +9978,7 @@ export const ListFromSelf = ( encode: (item) => listParse(ParseResult.encodeUnknown(Array$(item))) }, { + typeConstructor: { _tag: "effect/List" }, description: `List<${format(value)}>`, pretty: listPretty, arbitrary: listArbitrary, @@ -10046,6 +10069,7 @@ export const SortedSetFromSelf = ( encode: (item) => sortedSetParse(ParseResult.encodeUnknown(Array$(item)), ordI) }, { + typeConstructor: { _tag: "effect/SortedSet" }, description: `SortedSet<${format(value)}>`, pretty: sortedSetPretty, arbitrary: (arb, ctx) => sortedSetArbitrary(arb, ordA, ctx), diff --git a/packages/effect/src/SchemaAST.ts b/packages/effect/src/SchemaAST.ts index 344929d5491..85f9ec8c42a 100644 --- a/packages/effect/src/SchemaAST.ts +++ b/packages/effect/src/SchemaAST.ts @@ -52,6 +52,23 @@ export type AST = // annotations // ------------------------------------------------------------------------------------- +/** + * @category annotations + * @since 3.19.0 + * @experimental + */ +export type TypeConstructorAnnotation = { + readonly _tag: string + [key: PropertyKey]: unknown +} + +/** + * @category annotations + * @since 3.19.0 + * @experimental + */ +export const TypeConstructorAnnotationId: unique symbol = Symbol.for("effect/annotation/TypeConstructor") + /** * @category annotations * @since 3.10.0 @@ -326,6 +343,13 @@ export const getAnnotation: { Option.none() ) +/** + * @category annotations + * @since 3.19.0 + * @experimental + */ +export const getTypeConstructorAnnotation = getAnnotation(TypeConstructorAnnotationId) + /** * @category annotations * @since 3.10.0 diff --git a/packages/platform/src/Headers.ts b/packages/platform/src/Headers.ts index 2182fdad01f..cf97be60f12 100644 --- a/packages/platform/src/Headers.ts +++ b/packages/platform/src/Headers.ts @@ -59,6 +59,7 @@ const make = (input: Record.ReadonlyRecord): Mutable => * @category schemas */ export const schemaFromSelf: Schema.Schema = Schema.declare(isHeaders, { + typeConstructor: { _tag: "effect/platform/Headers" }, identifier: "Headers", equivalence: () => Record.getEquivalence(String.Equivalence) }) diff --git a/packages/platform/src/Multipart.ts b/packages/platform/src/Multipart.ts index 00b04816249..9c443699541 100644 --- a/packages/platform/src/Multipart.ts +++ b/packages/platform/src/Multipart.ts @@ -164,6 +164,7 @@ export class MultipartError extends Schema.TaggedError()("Multip * @category Schemas */ export const FileSchema: Schema.Schema = Schema.declare(isPersistedFile, { + typeConstructor: { _tag: "effect/platform/Multipart.PersistedFile" }, identifier: "PersistedFile", jsonSchema: { type: "string", diff --git a/packages/workflow/src/Workflow.ts b/packages/workflow/src/Workflow.ts index 8f926c6320c..cd3cf4de1c3 100644 --- a/packages/workflow/src/Workflow.ts +++ b/packages/workflow/src/Workflow.ts @@ -424,7 +424,9 @@ export class Complete extends Data.TaggedClass("Complete")<{ readonly success: Success readonly error: Error }): Schema.Schema> { - return Schema.declare((u): u is Complete => isResult(u) && u._tag === "Complete") + return Schema.declare((u): u is Complete => isResult(u) && u._tag === "Complete", { + typeConstructor: { _tag: "effect/workflow/Workflow.Complete" } + }) } /**