···89899090The compiler catches the bug before the code runs.
91919292+> **Note on casting:** The examples above use `as` for clarity, but in application code, prefer the `brand()` helper function which encapsulates the cast. See the [Smart Constructors](#smart-constructors) section below.
9393+9294### How It Works
93959496The `Brand<B>` type adds a phantom property that only exists at the type level:
+10-3
docs/guides/tutorial/07-the-effect-system.md
···270270 | { _tag: "NotFound"; url: string }
271271 | { _tag: "ServerError"; status: number }
272272273273+// Type guard for ApiError
274274+const isApiError = (e: unknown): e is ApiError =>
275275+ e !== null &&
276276+ typeof e === "object" &&
277277+ "_tag" in e &&
278278+ (e._tag === "NetworkError" || e._tag === "NotFound" || e._tag === "ServerError")
279279+273280const fetchJson = <T>(url: string): Eff<T, ApiError, unknown> =>
274281 pipe(
275282 fromPromise(() => fetch(url)),
···281288 : fromPromise(() => response.json())
282289 ),
283290 catchAll(e =>
284284- e && typeof e === "object" && "_tag" in e
285285- ? fail(e as ApiError)
291291+ isApiError(e)
292292+ ? fail(e)
286293 : fail({ _tag: "NetworkError", message: String(e) })
287294 )
288288- ) as Eff<T, ApiError, unknown>
295295+ )
289296290297// Usage
291298type User = { id: number; name: string }