The complete type toolkit exported from @blac/core. These utilities let you derive the state, args, deps, and instance shapes of a container class without hand-writing them, and the branded-ID helpers give you nominal InstanceId strings. Every signature on this page is quoted verbatim from source.
For a task-oriented walkthrough of typing blocs (generic parameters, inference, common pitfalls) see TypeScript. This page is the reference: one heading per export, the exact signature, what it does, and a small example.
All examples assume this setup, which is hidden from the rendered snippet but type-checked:
Cubit<S> is a StateContainer<S> that exposes mutation publicly.
That is the whole difference, and it is a real one: on StateContaineremit / patch / update are protected, so a container mutates itself
from its own methods and callers go through the API it chooses to publish.
Cubit re-declares the three as public for the cases where a caller
legitimately drives state from outside — test helpers, devtools
time-travel, benchmarks.
Reach for StateContainer when business logic should live in the class,
and Cubit when the caller owns the transitions.
Cubit<S> is a StateContainer<S> that exposes mutation publicly.
That is the whole difference, and it is a real one: on StateContaineremit / patch / update are protected, so a container mutates itself
from its own methods and callers go through the API it chooses to publish.
Cubit re-declares the three as public for the cases where a caller
legitimately drives state from outside — test helpers, devtools
time-travel, benchmarks.
Reach for StateContainer when business logic should live in the class,
and Cubit when the caller owns the transitions.
A StateContainer (and therefore Cubit) carries three type parameters: S (state), Args (serializable construction/identity data), and Deps (injected non-serializable handles). These utilities pull each one back out of a container class (the constructor, e.g. typeof CounterCubit), so you never have to re-declare a state shape that already lives on the class.
Extracts the state type from a container constructor as a Readonly<S>. This is the type you get back from useBloc and from the state getter — read-only, because state is immutable from the outside. Resolves to never if T is not a container constructor.
Extract the state type from a StateContainer, deeply readonly.
State is owned by the container: consumers read it and mutate only through
emit/patch, so nested writes are a compile error rather than a silent
desync from the change-tracking channel.
The same as ExtractState, but without the Readonly<> wrapper — the raw S as the class declared it. Reach for this only when you genuinely need a mutable view (for example, building the next state object before you emit it); prefer ExtractState everywhere a value is being read.
Extracts the Args type — the serializable data a bloc is constructed/identified with (see Passing Inputs). Falls back to void when the class declares no args. Note the match is against a zero-argument constructor shape (new () =>), which is how container subclasses are written.
Cubit<S> is a StateContainer<S> that exposes mutation publicly.
That is the whole difference, and it is a real one: on StateContaineremit / patch / update are protected, so a container mutates itself
from its own methods and callers go through the API it chooses to publish.
Cubit re-declares the three as public for the cases where a caller
legitimately drives state from outside — test helpers, devtools
time-travel, benchmarks.
Reach for StateContainer when business logic should live in the class,
and Cubit when the caller owns the transitions.
Extracts the Deps type — the injected non-serializable handles (clients, services, other blocs) a container depends on. Falls back to Record<string, never> (the “no deps” shape) when none are declared.
Cubit<S> is a StateContainer<S> that exposes mutation publicly.
That is the whole difference, and it is a real one: on StateContaineremit / patch / update are protected, so a container mutates itself
from its own methods and callers go through the API it chooses to publish.
Cubit re-declares the three as public for the cases where a caller
legitimately drives state from outside — test helpers, devtools
time-travel, benchmarks.
Reach for StateContainer when business logic should live in the class,
and Cubit when the caller owns the transitions.
The instance type of a container class with its state property narrowed to the Readonly state for that class. Useful when you want the full instance (methods, getters) but with a precisely-typed, read-only state.
Like InstanceReadonlyState, but the state property is the mutableS rather than Readonly<S>. Reach for it only when you specifically need a writable view of state on a typed instance.
A StateContainer instance keyed by its state type S rather than by a concrete class, with state narrowed to Readonly<S>. Use it when you want to describe “any container holding this state shape” without pinning a specific subclass.
The minimal constructor type for a container class, parameterized by state S. It is the constraint the extraction utilities (ExtractState, ExtractStateMutable, InstanceReadonlyState, InstanceState) match against. Use it where you only care that something is a container class.
BlaC tags instance-identity strings with a brand so a plain string cannot be passed where an InstanceId is expected. The brand is a compile-time-only phantom property keyed by a unique symbol; it has no runtime footprint — branded values are just strings at runtime.
The general nominal-typing helper: intersects a base type T with a phantom property under a private unique symbol, tagged by the brand identifier B. Two Brands with different B are incompatible even when T is identical, which is what prevents accidental mixing of similar primitive types.
type
typeUserId=string&{
[brand]:"UserId";
}
UserId=
typeBrand<T,B>=T&{
[brand]:B;
}
Nominal type helper, preventing accidental confusion between similar
primitive types.
@typeParam ― T - The base type
@typeParam ― B - The brand identifier
Brand<string,'UserId'>;
type
typeOrderId=string&{
[brand]:"OrderId";
}
OrderId=
typeBrand<T,B>=T&{
[brand]:B;
}
Nominal type helper, preventing accidental confusion between similar
primitive types.
@typeParam ― T - The base type
@typeParam ― B - The brand identifier
Brand<string,'OrderId'>;
declareconst
const u:UserId
u:
typeUserId=string&{
[brand]:"UserId";
}
UserId;
declarefunction
functionloadOrder(id:OrderId):void
loadOrder(
id: OrderId
id:
typeOrderId=string&{
[brand]:"OrderId";
}
OrderId):void;
functionloadOrder(id:OrderId):void
loadOrder(u);
Error ts(2345) ― Argument of type 'UserId' is not assignable to parameter of type 'OrderId'.
Type 'UserId' is not assignable to type '{ [brand]: "OrderId"; }'.
Types of property '[brand]' are incompatible.
Type '"UserId"' is not assignable to type '"OrderId"'.
The branded string type BlaC uses for state-container instance identities — BrandedId<'InstanceId'> by another name. Registry and identity APIs accept and return this rather than a bare string, so an arbitrary string cannot stand in for an instance key by accident.
declarefunction
functionlookup(id:InstanceId):void
lookup(
id: InstanceId
id:
typeInstanceId=string&{
[brand]:"InstanceId";
}
Branded string type for state container instance IDs.
InstanceId):void;
functionlookup(id:InstanceId):void
lookup('not-branded');
Error ts(2345) ― Argument of type 'string' is not assignable to parameter of type 'InstanceId'.
Type 'string' is not assignable to type '{ [brand]: "InstanceId"; }'.
The value-level helper that brands a plain string as an InstanceId. It is a pure cast at runtime (returns the input unchanged); its only job is to give you a typed InstanceId to hand to APIs that require one, without writing the as InstanceId assertion yourself.
const
const id:InstanceId
id:
typeInstanceId=string&{
[brand]:"InstanceId";
}
Branded string type for state container instance IDs.