Skip to content

Data.taggedEnum<WithGenerics<1>>().$match loses generic A inside arms #6249

@milkyskies

Description

@milkyskies

What version of Effect is running?

3.21.2

What steps can reproduce the bug?

import { Data } from "effect";

type Tree<A> = Data.TaggedEnum<{
  Branch: { children: ReadonlyArray<Tree<A>> };
  Leaf: { value: A };
}>;

interface TreeDef extends Data.TaggedEnum.WithGenerics<1> {
  readonly taggedEnum: Tree<this["A"]>;
}

const Tree = Data.taggedEnum<TreeDef>();

function collectValues<A>(node: Tree<A>): ReadonlyArray<A> {
  return Tree.$match(node, {
    Branch: ({ children }) => children.flatMap((c) => collectValues(c)),
    Leaf: ({ value }) => [value],
    //     ^^^^^ inferred as `unknown`, expected `A`
  });
}

TypeScript reports:

Type 'unknown[]' is not assignable to type 'readonly A[]'.

What is the expected behavior?

Inside the Leaf arm, value should be typed as A (the generic from the enclosing function), not unknown.
This matches $match's behavior on non-generic tagged enums.

What do you see instead?

value is unknown, so its use as A is rejected.

The curried form (Tree.$match(cases)(node)), explicit type args (Tree.$match<A, ...>), and Match.valueTags all exhibit the same collapse. Only Match.value(node).pipe(Match.tag(...), Match.exhaustive) preserves the generic, because Match.value<const I>(i: I) fixes I to the concrete Tree<A> instance before arms are typed.

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions