Type-safe queries with entity normalization, fine-grained reactivity, and streaming — for REST APIs and beyond.
1class GetUser extends RESTQuery {2 params = {3 id: t.number,4 };56 path = `/users/${this.params.id}`;78 result = {9 user: t.entity(User),10 };11}
1const UserProfile = component(async () => {2 const { user } = await fetchQuery(3 GetUser, { id: 42 }4 );56 return (7 <div>8 <h1>{user.name}</h1>9 <p>{user.email}</p>10 </div>11 );12});
REST-first. Protocol-agnostic. Built on Signalium. Works with React, Vue, Svelte, and more.
Everything you need for production data fetching, nothing you don't.
Class-based templates with type-safe params. Define once, use everywhere. Protocol-agnostic — switch from REST to GraphQL without changing usage sites.
Optimistic updates, cache invalidation, and rollback. Mutations share the same class-based pattern as queries for a consistent API.
A zero-alloc DSL that is both a runtime validator and TypeScript type. Number masks, not objects. Designed for resilience — optional fields fall back, arrays filter unknown items.
Normalized, deduplicated, identity-stable proxy objects. The same user across 10 queries is the exact same reference. Update once, see it everywhere.
Built on Signalium. Lazy entanglement means you only pay for what you read. No wasted renders, no stale closures. Works outside React too.
First-class real-time subscriptions on entities. WebSocket, SSE, or any source — define __subscribe and Fetchium handles the lifecycle.
Normalized entity store with configurable GC, deduplication, and stale-while-revalidate. Smart enough to skip the network when data is fresh.
Polling, window focus refetch, network reconnect, and manual invalidation. Configure per-query or globally. Dynamic intervals based on response state.
When the same user appears in a post and a profile, Fetchium returns the exact same object. Update it anywhere, see it everywhere — no manual cache invalidation.
Entity proxies backed by signals. Lazy entanglement means you only pay for what you read.
Deep cloning with structural sharing at the React boundary. Compatible with memo, compiler, and Suspense.
1class User extends Entity {2 __typename = t.typename('User');3 id = t.id;4 name = t.string;5 email = t.string;6 avatar = t.optional(t.string);7 createdAt = t.format('date-time');89 get fullName() {10 return this.name;11 }12}
1const { user } = await fetchQuery(GetUser, { id: '1' });2const { post } = await fetchQuery(GetPost, { id: '5' });34// If post #5's author is user #1:5post.author === user; // true
1// Optional fields fall back gracefully2result = {3 name: t.string,4 bio: t.optional(t.string), // unknown? -> undefined5};67// Arrays filter out unparseable items8result = {9 items: t.array(10 t.union(TextItem, ImageItem) // unknown? -> skipped11 ),12};
Fetchium's type system is designed for resilience. Optional fields fall back to undefined. Arrays silently filter unknown types. Your app keeps running while the API evolves.
The type DSL uses number masks under the hood — not objects. A type like t.optional(t.string) creates zero allocations.
| Fetchium | TanStack Query | Apollo Client | |
|---|---|---|---|
| REST support | First class | BYO fetch fn | — |
| GraphQL support | Adapter | — | First class |
| Entity normalization | ✓ | — | ✓ |
| End-to-end type safety | ✓ | Partial | Partial |
| Fine-grained reactivity | ✓ | — | — |
| Streaming / real-time | ✓ | — | Subscriptions |
| Protocol agnostic | ✓ | — | — |
| Zero-alloc type DSL | ✓ | — | — |
Add Fetchium to your project and define your first query in minutes.