···264264 retry,
265265 pipe,
266266 match,
267267+ hasProperties,
267268 runPromise,
268269 runPromiseExit,
269270} from "../../src/index"
···305306306307// Type guard - validates the shape at runtime without casting
307308const isUser = (data: unknown): data is User =>
308308- typeof data === "object" &&
309309- data !== null &&
310310- "id" in data &&
311311- "name" in data &&
312312- "email" in data
309309+ hasProperties("id", "name", "email")(data)
313310314311// =============================================================================
315312// SECTION 2: Fetch as an Effect
···267267268268```typescript
269269import {
270270- type Eff, succeed, fail, pipe, flatMap, mapEff, catchAll, fromPromise
270270+ type Eff, succeed, fail, pipe, flatMap, mapEff, catchAll, fromPromise, isObject, hasProperties
271271} from "purus-ts"
272272273273type ApiError =
···277277278278// Type guard for ApiError
279279const isApiError = (e: unknown): e is ApiError =>
280280- e !== null &&
281281- typeof e === "object" &&
282282- "_tag" in e &&
280280+ hasProperties("_tag")(e) &&
283281 (e._tag === "NetworkError" || e._tag === "NotFound" || e._tag === "ServerError")
284282285283const fetchJson = <T>(url: string): Eff<T, ApiError, unknown> =>
+2-5
examples/http-client/with-purus.ts
···3535 retry,
3636 pipe,
3737 match,
3838+ hasProperties,
3839 runPromise,
3940 runPromiseExit,
4041} from "../../src/index"
···76777778// Type guard - validates the shape at runtime without casting
7879const isUser = (data: unknown): data is User =>
7979- typeof data === "object" &&
8080- data !== null &&
8181- "id" in data &&
8282- "name" in data &&
8383- "email" in data
8080+ hasProperties("id", "name", "email")(data)
84818582// =============================================================================
8683// SECTION 2: Fetch as an Effect
+6
src/data/guards.ts
···9393 <K extends string>(key: K) =>
9494 <T>(x: T): x is T & Record<K, unknown> =>
9595 isObject(x) && key in x
9696+9797+/** Creates a guard that checks if an object has all specified properties */
9898+export const hasProperties =
9999+ <K extends string>(...keys: K[]) =>
100100+ <T>(x: T): x is T & Record<K, unknown> =>
101101+ isObject(x) && keys.every((k) => k in x)