Narrowing down the type of a Match pipe

In ts-pattern, I can do the following:
import { match, Pattern } from "ts-pattern";

const status = match(mockMessage)
  .returnType<"read-by-user" | "pending" | "optimistic">()
  .with({ id: Pattern.string.startsWith("optimistic") }, () => "optimistic")
  .with({ readAt: Pattern.nonNullable }, () => "read-by-user")
  .otherwise(() => "pending");

status; // "optimistic" | "read-by-user" | "pending"

However, with Match, I need to assert all values as const since I can't find a way to enforce a return type (making it a little bit more verbose):
import { Match, String, Predicate } from "effect";

const result = Match.value(mockMessage).pipe(
  Match.when({ id: String.startsWith("optimistic") }, () => "optimistic" as const),
  Match.when({ readAt: Predicate.isNotNullable }, () => "read-by-user" as const),
  Match.orElse(() => "pending" as const),
) satisfies "read-by-user" | "pending" | "optimistic";

I tried using withReturnType, however, I get a type error:
const result = Match.value(mockMessage).pipe(
  Match.withReturnType<"optimistic" | "read-by-user" | "pending">(),
  Match.when({ id: String.startsWith("optimistic") }, () => "optimistic"),
  Match.when({ readAt: Predicate.isNotNullable }, () => "read-by-user"),
  Match.orElse(() => "pending"),
);

const result: unknown

Type string is not assignable to type never

Is satisfies with as const the way to go with Match?
Was this page helpful?