Utility Types
import type { StoreOf, StateOf, RawStateOf, DepsOf, DetectConflicts } from '@hurum/core'Type utilities for extracting types from a store definition. Useful when writing functions, hooks, or tests that need to reference store types without duplicating them.
StoreOf<T>
Section titled “StoreOf<T>”Extracts the store instance type from a store definition.
type StoreOf<T> = T extends StoreDefinition<infer D, infer R, infer C, infer I> ? StoreInstance<D, R, C, I> : neverExample
Section titled “Example”const CartStore = Store({ state: { items: [] as CartItem[] } }) .computed({ total: (s) => s.items.reduce((sum, i) => sum + i.price, 0) }) .intents(CartIntents) .executors(AddItemExec)
// Extract the instance typetype CartInstance = StoreOf<typeof CartStore>
function processCart(store: CartInstance) { const state = store.getState() // ^? { items: CartItem[], total: number }}StateOf<T>
Section titled “StateOf<T>”Extracts the combined state type (raw + computed) from a store definition. This is the type returned by store.getState().
type StateOf<T> = T extends StoreDefinition<unknown, infer R, infer C> ? ResolvedState<R> & C : neverExample
Section titled “Example”type CartState = StateOf<typeof CartStore>// { items: CartItem[], total: number }
function renderTotal(state: CartState) { return `$${state.total.toFixed(2)}`}RawStateOf<T>
Section titled “RawStateOf<T>”Extracts only the raw state type (without computed fields) from a store definition. This is the shape that on handlers must return.
type RawStateOf<T> = T extends StoreDefinition<unknown, infer R, unknown> ? R : neverExample
Section titled “Example”type CartRawState = RawStateOf<typeof CartStore>// { items: CartItem[] }// Note: `total` is NOT included (it's computed)DepsOf<T>
Section titled “DepsOf<T>”Extracts the dependency type from a store definition.
type DepsOf<T> = T extends StoreDefinition<infer D, unknown, unknown> ? D : neverExample
Section titled “Example”const CartStore = Store({ state: { items: [] as CartItem[] } }) .deps<{ repo: CartRepo; analytics: Analytics }>()
type CartDeps = DepsOf<typeof CartStore>// { repo: CartRepo; analytics: Analytics }
function createTestDeps(): CartDeps { return { repo: new MockCartRepo(), analytics: new MockAnalytics(), }}DetectConflicts<A, B>
Section titled “DetectConflicts<A, B>”Detects conflicting keys between two dependency types. If the same key exists in both A and B with different types, it surfaces as a union of the conflicting key names.
type DetectConflicts<A, B> = { [K in keyof A & keyof B]: A[K] extends B[K] ? B[K] extends A[K] ? never : K : K}[keyof A & keyof B]Example
Section titled “Example”type ParentDeps = { api: RestApi; logger: Logger }type ChildDeps = { api: GraphQLApi; cache: Cache }
type Conflicts = DetectConflicts<ParentDeps, ChildDeps>// 'api' -- because RestApi !== GraphQLApi
// Use this to catch mismatches early:type AssertNoConflicts = [Conflicts] extends [never] ? true : false// ^? false -- there IS a conflict- These types work with the store definition (the builder), not the instance. Pass
typeof MyStore, not a store instance. StateOfincludes resolved nested state. ANested(ChildStore)field resolves to the child’s full state (raw + computed).- All utility types return
neverif the input is not a validStoreDefinition.