diff --git a/.changeset/lovely-monkeys-compete.md b/.changeset/lovely-monkeys-compete.md new file mode 100644 index 0000000000..f2863fed18 --- /dev/null +++ b/.changeset/lovely-monkeys-compete.md @@ -0,0 +1,17 @@ +--- +"effect": patch +--- + +Support for the tacit usage of external handlers for `Match.tag` and `Match.tagStartsWith` functions + +```ts +type Value = { _tag: "A"; a: string } | { _tag: "B"; b: number } +const handlerA = (_: { _tag: "A"; a: number }) => _.a + +// $ExpectType string | number +pipe( + M.type(), + M.tag("A", handlerA), // <-- no type issue + M.orElse((_) => _.b) +)(value) +``` diff --git a/packages/effect/dtslint/Match.ts b/packages/effect/dtslint/Match.ts index 22da26d860..81eff5a038 100644 --- a/packages/effect/dtslint/Match.ts +++ b/packages/effect/dtslint/Match.ts @@ -3,6 +3,7 @@ import * as M from "effect/Match" type Value = { _tag: "A"; a: number } | { _tag: "B"; b: number } const value = { _tag: "A", a: 123 } as Value +const handlerA = (_: { _tag: "A"; a: number }) => _.a.toString() // ------------------------------------------------------------------------------------- // valueTags @@ -139,3 +140,27 @@ pipe( C: () => false }) )(value) + +// ------------------------------------------------------------------------------------- +// tag +// ------------------------------------------------------------------------------------- + +// tacit usage of external handler +// $ExpectType string | number +pipe( + M.type(), + M.tag("A", handlerA), + M.orElse((_) => _.b) +)(value) + +// ------------------------------------------------------------------------------------- +// tagStartsWith +// ------------------------------------------------------------------------------------- + +// tacit usage of external handler +// $ExpectType string | number +pipe( + M.type(), + M.tagStartsWith("A", handlerA), + M.orElse((_) => _.b) +)(value) diff --git a/packages/effect/src/Match.ts b/packages/effect/src/Match.ts index 28c7f94f7f..c402bcef36 100644 --- a/packages/effect/src/Match.ts +++ b/packages/effect/src/Match.ts @@ -6,7 +6,7 @@ import * as internal from "./internal/matcher.js" import type * as Option from "./Option.js" import type { Pipeable } from "./Pipeable.js" import * as Predicate from "./Predicate.js" -import type { Contravariant, Covariant, UnionToIntersection } from "./Types.js" +import type * as T from "./Types.js" import type { Unify } from "./Unify.js" /** @@ -36,11 +36,11 @@ export type Matcher extends Pipeable { readonly _tag: "TypeMatcher" readonly [MatcherTypeId]: { - readonly _input: Contravariant - readonly _filters: Covariant - readonly _remaining: Covariant - readonly _result: Covariant - readonly _return: Covariant + readonly _input: T.Contravariant + readonly _filters: T.Covariant + readonly _remaining: T.Covariant + readonly _result: T.Covariant + readonly _return: T.Covariant } readonly cases: ReadonlyArray add(_case: Case): TypeMatcher @@ -55,10 +55,10 @@ export interface ValueMatcher - readonly _filters: Covariant - readonly _result: Covariant - readonly _return: Covariant + readonly _input: T.Contravariant + readonly _filters: T.Covariant + readonly _result: T.Covariant + readonly _return: T.Covariant } readonly provided: Provided readonly value: Either.Either @@ -196,15 +196,15 @@ export const whenAnd: < R, const P extends ReadonlyArray | Types.PatternBase>, Ret, - Fn extends (_: Types.WhenMatch>) => Ret + Fn extends (_: Types.WhenMatch>) => Ret >( ...args: [...patterns: P, f: Fn] ) => ( self: Matcher ) => Matcher< I, - Types.AddWithout>>, - Types.ApplyFilters>>>, + Types.AddWithout>>, + Types.ApplyFilters>>>, A | ReturnType, Pr > = internal.whenAnd @@ -297,7 +297,7 @@ export const discriminatorsExhaustive: ( * @since 1.0.0 */ export const tag: & string, Ret, B extends Ret>( - ...pattern: [first: P, ...values: Array

, f: (_: Extract>) => B] + ...pattern: [first: P, ...values: Array

, f: (_: Extract, Record<"_tag", P>>) => B] ) => ( self: Matcher ) => Matcher< @@ -315,7 +315,7 @@ export const tag: & string, Ret, B extends R */ export const tagStartsWith: ( pattern: P, - f: (_: Extract>) => B + f: (_: Extract, Record<"_tag", `${P}${string}`>>) => B ) => ( self: Matcher ) => Matcher< @@ -692,7 +692,7 @@ export declare namespace Types { /** * @since 1.0.0 */ - export type ArrayToIntersection> = UnionToIntersection< + export type ArrayToIntersection> = T.UnionToIntersection< A[number] >