effect icon indicating copy to clipboard operation
effect copied to clipboard

Provide runtime type detection API for Effect data types

Open jasonkuhrt opened this issue 1 month ago • 5 comments

Currently, there's no standard way to detect Effect data types (Option, Either, etc.) at runtime and retrieve their type names for generic dispatch systems (like trait implementations).

Use case: Building a trait system that needs to:

  1. Detect if a value is an Effect type (vs native JS type)
  2. Get the type name (e.g., "Option", "Either") for dispatch

Current approach:

// Check for TypeId symbol and parse description
for (const typeId of [Option.TypeId, Either.TypeId]) {
  if (typeId in value) {
    const typeName = typeId.description?.slice(7) // "effect/Option" → "Option"
    return typeName
  }
}

Issues:

  • Brittle: relies on Symbol.description format "effect/TypeName"
  • Requires maintaining hardcoded list of TypeId symbols
  • No way to detect all Effect types generically

Proposed solution:

Effect.getTypeName(value) // "Option" | "Either" | ... | null

This single API provides both detection (non-null) and identification (the name), enabling generic handling of Effect types in libraries without brittle Symbol parsing.

jasonkuhrt avatar Nov 12 '25 05:11 jasonkuhrt

there's no standard way to detect Effect data types

For this there are type guards like Effect.isEffect, Option.isOption, Either.isEither, etc...

gcanti avatar Nov 12 '25 05:11 gcanti

Hey @gcanti yeah that gets some mileage here, but imagine I want to be able to extract the type name of a given value without knowing beforehand the possible set of types. In other words a contract about how value type metadata is stored for arbitrary reflection at runtime.

jasonkuhrt avatar Nov 12 '25 18:11 jasonkuhrt

there's no standard way to detect Effect data types

@jasonkuhrt I’ve always thought of this as _tag.

Effect data types (Option, Either, etc.) at runtime

Is Either a runtime data type? I don’t think it can be instantiated. “What data type is Right(x)” being “Right” according to its _tag is at least consistent with that. Thinking of it as “an Either” isn’t necessarily correct I don’t think. It happens to satisfy “Either” but it could satisfy many other things.

alex-dixon avatar Nov 16 '25 16:11 alex-dixon

@alex-dixon Hey, iiuc _tag does not track the type (e.g. Either) but rather a type member (e.g. Right, Left – what we would call constructor iirc in Haskell). It seems that there is no way to know that Right and Left tag values stem from Either, by design.

jasonkuhrt avatar Nov 17 '25 15:11 jasonkuhrt

Haskell has full type erasure iirc, the contract is that if your function is generic over some type, it cannot change its behaviour based on that type.

Reflection is a very Java way of approaching this. Imho the beauty of effect is partly that it provides strong type guarantees at compile time and doesn't have the baggage of runtime types

dpnova avatar Nov 29 '25 09:11 dpnova