From 9b4ed20ce4fd12755278aad7d702824219b5183f Mon Sep 17 00:00:00 2001 From: Maxim Khramtsov Date: Mon, 8 Jul 2024 07:27:09 +0200 Subject: [PATCH] For `Data.TaggedEnum` added capitalized constructor naming convention. (#2785) Co-authored-by: maksim.khramtsov Co-authored-by: Tim --- .changeset/happy-jeans-invent.md | 6 ++++++ packages/cli/src/internal/prompt/confirm.ts | 2 +- packages/cli/src/internal/prompt/date.ts | 2 +- packages/cli/src/internal/prompt/file.ts | 4 ++-- packages/cli/src/internal/prompt/number.ts | 4 ++-- packages/cli/src/internal/prompt/select.ts | 2 +- packages/cli/src/internal/prompt/text.ts | 2 +- packages/effect/src/Data.ts | 24 +++++++++++++++------ packages/effect/test/Data.test.ts | 22 +++++++++---------- 9 files changed, 42 insertions(+), 26 deletions(-) create mode 100644 .changeset/happy-jeans-invent.md diff --git a/.changeset/happy-jeans-invent.md b/.changeset/happy-jeans-invent.md new file mode 100644 index 00000000000..f5e93e0f140 --- /dev/null +++ b/.changeset/happy-jeans-invent.md @@ -0,0 +1,6 @@ +--- +"effect": major +--- + +For `Data.TaggedEnum` added capitalized constructor naming convention. +Helper functions `$is` and `$match` have been renamed to `is` and `match`. diff --git a/packages/cli/src/internal/prompt/confirm.ts b/packages/cli/src/internal/prompt/confirm.ts index 1bab440afc4..75515305d6f 100644 --- a/packages/cli/src/internal/prompt/confirm.ts +++ b/packages/cli/src/internal/prompt/confirm.ts @@ -100,7 +100,7 @@ function renderSubmission(value: boolean, options: Options) { function handleRender(options: Options) { return (_: State, action: Prompt.Prompt.Action) => { - return Action.$match(action, { + return Action.match(action, { Beep: () => Effect.succeed(renderBeep), NextFrame: ({ state }) => renderNextFrame(state, options), Submit: ({ value }) => renderSubmission(value, options) diff --git a/packages/cli/src/internal/prompt/date.ts b/packages/cli/src/internal/prompt/date.ts index 8aca15a4094..114d80c89fd 100644 --- a/packages/cli/src/internal/prompt/date.ts +++ b/packages/cli/src/internal/prompt/date.ts @@ -233,7 +233,7 @@ const defaultLocales: Prompt.Prompt.DateOptions["locales"] = { function handleRender(options: DateOptions) { return (state: State, action: Prompt.Prompt.Action) => { - return Action.$match(action, { + return Action.match(action, { Beep: () => Effect.succeed(renderBeep), NextFrame: ({ state }) => renderNextFrame(state, options), Submit: () => renderSubmission(state, options) diff --git a/packages/cli/src/internal/prompt/file.ts b/packages/cli/src/internal/prompt/file.ts index a47f23d3b46..c415373324c 100644 --- a/packages/cli/src/internal/prompt/file.ts +++ b/packages/cli/src/internal/prompt/file.ts @@ -33,7 +33,7 @@ type Confirm = Data.TaggedEnum<{ }> const Confirm = Data.taggedEnum() -const showConfirmation = Confirm.$is("Show") +const showConfirmation = Confirm.is("Show") const renderBeep = Doc.render(Doc.beep, { style: "pretty" }) @@ -235,7 +235,7 @@ function renderSubmission(value: string, options: FileOptions) { function handleRender(options: FileOptions) { return (_: State, action: Prompt.Prompt.Action) => { - return Action.$match(action, { + return Action.match(action, { Beep: () => Effect.succeed(renderBeep), NextFrame: ({ state }) => renderNextFrame(state, options), Submit: ({ value }) => renderSubmission(value, options) diff --git a/packages/cli/src/internal/prompt/number.ts b/packages/cli/src/internal/prompt/number.ts index fc7442eb7ff..4b2ca1997cd 100644 --- a/packages/cli/src/internal/prompt/number.ts +++ b/packages/cli/src/internal/prompt/number.ts @@ -206,7 +206,7 @@ const initialState: State = { function handleRenderInteger(options: IntegerOptions) { return (state: State, action: Prompt.Prompt.Action) => { - return Action.$match(action, { + return Action.match(action, { Beep: () => Effect.succeed(renderBeep), NextFrame: ({ state }) => renderNextFrame(state, options), Submit: () => renderSubmission(state, options) @@ -302,7 +302,7 @@ export const integer = (options: Prompt.Prompt.IntegerOptions): Prompt.Prompt) => { - return Action.$match(action, { + return Action.match(action, { Beep: () => Effect.succeed(renderBeep), NextFrame: ({ state }) => renderNextFrame(state, options), Submit: () => renderSubmission(state, options) diff --git a/packages/cli/src/internal/prompt/select.ts b/packages/cli/src/internal/prompt/select.ts index fde52276a6f..da951c6aa12 100644 --- a/packages/cli/src/internal/prompt/select.ts +++ b/packages/cli/src/internal/prompt/select.ts @@ -182,7 +182,7 @@ function processNext(state: State, choices: Prompt.Prompt.SelectOptions["c function handleRender(options: SelectOptions) { return (state: State, action: Prompt.Prompt.Action) => { - return Action.$match(action, { + return Action.match(action, { Beep: () => Effect.succeed(renderBeep), NextFrame: ({ state }) => renderNextFrame(state, options), Submit: () => renderSubmission(state, options) diff --git a/packages/cli/src/internal/prompt/text.ts b/packages/cli/src/internal/prompt/text.ts index f2a20beda82..eb9fec5a055 100644 --- a/packages/cli/src/internal/prompt/text.ts +++ b/packages/cli/src/internal/prompt/text.ts @@ -210,7 +210,7 @@ const initialState: State = { function handleRender(options: Options) { return (state: State, action: Prompt.Prompt.Action) => { - return Action.$match(action, { + return Action.match(action, { Beep: () => Effect.succeed(renderBeep), NextFrame: ({ state }) => renderNextFrame(state, options), Submit: () => renderSubmission(state, options) diff --git a/packages/effect/src/Data.ts b/packages/effect/src/Data.ts index d793a1c21d6..96bca5ddf07 100644 --- a/packages/effect/src/Data.ts +++ b/packages/effect/src/Data.ts @@ -260,12 +260,22 @@ export const Structural: new( * @category models */ export type TaggedEnum< - A extends Record> & UntaggedChildren + A extends + & Record> + & CapitalConstructorNames + & UntaggedChildren > = keyof A extends infer Tag ? Tag extends keyof A ? Types.Simplify<{ readonly _tag: Tag } & { readonly [K in keyof A[Tag]]: A[Tag][K] }> : never : never +type CapitalConstructorNames = Record< + Uncapitalize, + keyof A extends infer X extends string + ? X extends Uncapitalize ? `Use capitalized constructor name. Did you mean "${Capitalize}"?` : never + : never +> + type ChildrenAreTagged = keyof A extends infer K ? K extends keyof A ? "_tag" extends keyof A[K] ? true : false : never @@ -336,8 +346,8 @@ export declare namespace TaggedEnum { readonly [Tag in A["_tag"]]: Case.Constructor, "_tag"> } & { - readonly $is: (tag: Tag) => (u: unknown) => u is Extract - readonly $match: { + readonly is: (tag: Tag) => (u: unknown) => u is Extract + readonly match: { < Cases extends { readonly [Tag in A["_tag"]]: (args: Extract) => any @@ -356,7 +366,7 @@ export declare namespace TaggedEnum { * @since 3.2.0 */ export interface GenericMatchers> { - readonly $is: ( + readonly is: ( tag: Tag ) => { >( @@ -364,7 +374,7 @@ export declare namespace TaggedEnum { ): u is T & { readonly _tag: Tag } (u: unknown): u is Extract, { readonly _tag: Tag }> } - readonly $match: { + readonly match: { < A, B, @@ -482,9 +492,9 @@ export const taggedEnum: { } = () => new Proxy({}, { get(_target, tag, _receiver) { - if (tag === "$is") { + if (tag === "is") { return Predicate.isTagged - } else if (tag === "$match") { + } else if (tag === "match") { return taggedMatch } return tagged(tag as string) diff --git a/packages/effect/test/Data.test.ts b/packages/effect/test/Data.test.ts index 2420c6c1deb..62dcb427597 100644 --- a/packages/effect/test/Data.test.ts +++ b/packages/effect/test/Data.test.ts @@ -187,10 +187,10 @@ describe("Data", () => { InternalServerError: { reason: string } }> const { - $is, - $match, InternalServerError, - NotFound + NotFound, + is, + match } = Data.taggedEnum() const a = NotFound() @@ -206,9 +206,9 @@ describe("Data", () => { expect(Equal.equals(a, b)).toBe(false) expect(Equal.equals(b, c)).toBe(true) - expect($is("NotFound")(a)).toBe(true) - expect($is("InternalServerError")(a)).toBe(false) - const matcher = $match({ + expect(is("NotFound")(a)).toBe(true) + expect(is("InternalServerError")(a)).toBe(false) + const matcher = match({ NotFound: () => 0, InternalServerError: () => 1 }) @@ -227,7 +227,7 @@ describe("Data", () => { interface ResultDefinition extends Data.TaggedEnum.WithGenerics<2> { readonly taggedEnum: Result } - const { $is, $match, Failure, Success } = Data.taggedEnum() + const { Failure, Success, is, match } = Data.taggedEnum() const a = Success({ value: 1 }) satisfies Result const b = Failure({ error: "test" }) satisfies Result @@ -247,7 +247,7 @@ describe("Data", () => { const bResult = Failure({ error: "boom" }) as Result assert.strictEqual( - $match(aResult, { + match(aResult, { Success: (_) => 1, Failure: (_) => 2 }), @@ -255,7 +255,7 @@ describe("Data", () => { ) const result = pipe( bResult, - $match({ + match({ Success: (_) => _.value, Failure: (_) => _.error }) @@ -263,11 +263,11 @@ describe("Data", () => { result satisfies string | number assert.strictEqual(result, "boom") - assert($is("Success")(aResult)) + assert(is("Success")(aResult)) aResult satisfies { readonly _tag: "Success"; readonly value: number } assert.strictEqual(aResult.value, 1) - assert($is("Failure")(bResult)) + assert(is("Failure")(bResult)) bResult satisfies { readonly _tag: "Failure"; readonly error: string } assert.strictEqual(bResult.error, "boom") })