diff --git a/.changeset/cold-loops-arrive.md b/.changeset/cold-loops-arrive.md new file mode 100644 index 00000000000..b21395c10e2 --- /dev/null +++ b/.changeset/cold-loops-arrive.md @@ -0,0 +1,5 @@ +--- +"effect": patch +--- + +Fix $match generic type parameter inference inside arms (#6249) diff --git a/packages/effect/dtslint/Data.tst.ts b/packages/effect/dtslint/Data.tst.ts index f3db883328b..3bee7fb3960 100644 --- a/packages/effect/dtslint/Data.tst.ts +++ b/packages/effect/dtslint/Data.tst.ts @@ -189,5 +189,30 @@ describe("Data", () => { expect().type.toBe<((args: { readonly a: A }) => { readonly _tag: "A"; readonly a: A })>() expect().type.toBe<((args: { readonly b?: B }) => { readonly _tag: "B"; readonly b?: B })>() }) + + it("should preserve the generic type parameter inside $match arms (#6249)", () => { + type TE = Data.TaggedEnum<{ + Leaf: { value: T } + Branch: { children: ReadonlyArray> } + }> + + interface TEDefinition extends Data.TaggedEnum.WithGenerics<1> { + readonly taggedEnum: TE + } + + const TE = Data.taggedEnum() + + function collectValues(node: TE): ReadonlyArray { + return TE.$match(node, { + Leaf: (leaf) => { + expect(leaf.value).type.toBe() + return [leaf.value] + }, + Branch: (branch) => branch.children.flatMap(collectValues) + }) + } + + expect(collectValues).type.toBe<(node: TE) => ReadonlyArray>() + }) }) }) diff --git a/packages/effect/src/Data.ts b/packages/effect/src/Data.ts index f4910d487fe..427463d0a93 100644 --- a/packages/effect/src/Data.ts +++ b/packages/effect/src/Data.ts @@ -389,18 +389,16 @@ export declare namespace TaggedEnum { } readonly $match: { < - A, - B, - C, - D, - Cases extends { - readonly [Tag in Z["taggedEnum"]["_tag"]]: ( - args: Extract, { readonly _tag: Tag }> + const Self extends TaggedEnum.Kind, + const Cases extends { + readonly [Tag in Self["_tag"]]: ( + args: Extract ) => any } >( - cases: Cases & { [K in Exclude]: never } - ): (self: TaggedEnum.Kind) => Unify> + self: Self, + cases: Cases & { [K in Exclude]: never } + ): Unify> < A, B, @@ -412,9 +410,8 @@ export declare namespace TaggedEnum { ) => any } >( - self: TaggedEnum.Kind, cases: Cases & { [K in Exclude]: never } - ): Unify> + ): (self: TaggedEnum.Kind) => Unify> } } }