Deep Signals
Deep structural reactivity for plain objects / arrays / Sets built on top of alien-signals.
Hooks for Svelte, Vue, and React.
Core idea: wrap a data tree in a Proxy that lazily creates per-property signals the first time you read them. Deep mutations emit batched patch objects (in a JSON-patch inspired style) that you can track with watch().
Features
- Lazy: signals & child proxies created only when touched.
- Deep: nested objects, arrays, Sets proxied.
- Patch stream: microtask‑batched granular mutations (paths + op) for syncing external stores / framework adapters.
- Getter => computed: property getters become derived (readonly) signals automatically.
- Sets:
add/delete/clear/...methods emit patches; object entries get synthetic stable ids. - Configurable synthetic IDs: custom property generator - the synthetic ID is used in the paths of patches to identify objects in sets. By default attached as
@idproperty. - Read-only properties: protect specific properties from modification.
- Shallow escape hatch: wrap sub-objects with
shallow(obj)to track only reference replacement.
Install
pnpm add @ng-org/alien-deepsignals
# or
npm i @ng-org/alien-deepsignals
Quick start
import { deepSignal } from "@ng-org/alien-deepsignals";
const state = deepSignal({
count: 0,
user: { name: "Ada" },
items: [{ id: "i1", qty: 1 }],
settings: new Set(["dark"]),
});
state.count++; // mutate normally
state.user.name = "Grace"; // nested write
state.items.push({ id: "i2", qty: 2 });
state.settings.add("beta");
Frontend Hooks
We provide hooks for Svelte 3/4, Svelte 5, Vue, and React so that you can use deepSignal objects in your frontend framework. Modifying the object within those components works as usual, just that the component will rerender automatically when the object changed (by a modification in the component or a modification from elsewhere).
Note that you can pass existing deepSignal objects to useDeepSignal (that you are using elsewhere too, for example as shared state) as well as plain JavaScript objects (which are then wrapped).
You can (and are often advised to) use deepSignals as a shared state (and sub objects thereof) across components.
React
import { useDeepSignal } from "@ng-org/alien-deepsignals/react";
import { DeepSignal } from "@ng-org/alien-deepsignals";
import UserComponent from "./User.tsx";
import type { User } from "./types.ts";
function UserManager() {
const users: DeepSignal<User[]> = useDeepSignal([{ username: "Bob" }]);
return users.map((user) => <UserComponent key={user.id} user={user} />);
}
In child component User.tsx:
function UserComponent({ user }: { user: DeepSignal<User> }) {
// Modifications here will trigger a re-render in the parent component
// which updates this component.
// For performance reasons, you are advised to call `useDeepSignal`
// close to where its return value is used.
return <input type="text" value={user.name} />;
}
Vue
In component UserManager.vue
<script setup lang="ts">
import { useDeepSignal } from "@ng-org/alien-deepsignals/vue";
import { DeepSignal } from "@ng-org/alien-deepsignals";
import UserComponent from "./User.vue";
import type { User } from "./types.ts";
const users: DeepSignal<User[]> = useDeepSignal([{ username: "Bob", id: 1 }]);
</script>
<template>
<UserComponent v-for="user in users" :key="user.id" :user="user" />
</template>
In a child component, User.vue
<script setup lang="ts">
const props = defineProps<{
user: DeepSignal<User>;
}>();
// The component only rerenders when user.name changes.
// It behaves the same as an object wrapped with `reactive()`
const user = props.user;
</script>
<template>
<input type="text" v-model:value="user.name" />
</template>
Svelte 3 / 4
import { useDeepSignal } from "@ng-org/alien-deepsignals/svelte4";
// `users` is a store of type `{username: string}[]`
const users = useDeepSignal([{ username: "Bob" }]);
Svelte 5
import { useDeepSignal } from "@ng-org/alien-deepsignals/svelte";
// `users` is a rune of type `{username: string}[]`
const users = useDeepSignal([{ username: "Bob" }]);
Other Frameworks
Integrating new frontend frameworks is fairly easy. Get in touch if you are interested.
Reference
Interfaces
DeepPatchBatch
Defined in: sdk/js/alien-deepsignals/src/types.ts:23
Batched patch payload tagged with a monotonically increasing version.
Properties
patches
patches:
DeepPatch[]
Defined in: sdk/js/alien-deepsignals/src/types.ts:25
version
version:
number
Defined in: sdk/js/alien-deepsignals/src/types.ts:24
DeepSignalOptions
Defined in: sdk/js/alien-deepsignals/src/types.ts:42
Internal
Options to pass to deepSignal
Properties
propGenerator?
optionalpropGenerator:DeepSignalPropGenFn
Defined in: sdk/js/alien-deepsignals/src/types.ts:47
An optional function that is called when new objects are attached and that may return additional properties to be attached.
readOnlyProps?
optionalreadOnlyProps:string[]
Defined in: sdk/js/alien-deepsignals/src/types.ts:60
Optional: Properties that are made read-only in objects. Can only be attached by propGenerator or must already be member of the new object before attaching it.
replaceProxiesInBranchOnChange?
optionalreplaceProxiesInBranchOnChange:boolean
Defined in: sdk/js/alien-deepsignals/src/types.ts:66
If set to true, all proxies in the branch to a modified nested property are replaced.
This has no effect except for equality checks (===). This is necessary for react to notice the change.
Default
false;
subscriberFactories?
optionalsubscriberFactories:Set<ExternalSubscriberFactory<any>>
Defined in: sdk/js/alien-deepsignals/src/types.ts:71
syntheticIdPropertyName?
optionalsyntheticIdPropertyName:string
Defined in: sdk/js/alien-deepsignals/src/types.ts:54
The property name which should be used as an object identifier in sets.
You will see it when patches are generated with a path to an object in a set.
The syntheticId will be a patch element then.
Objects with existing properties matching syntheticIdPropertyName keep their values (not overwritten).
DeepSignalSet
Defined in: sdk/js/alien-deepsignals/src/types.ts:187
Type alias for DeepSignal<Set<T>> and reactive Set wrapper that accepts raw or proxied entries.
Additionally it is decorated with DeepSignalSetProps.
Extends
Set<DeepSignal<T>>.SetIterator<DeepSignal<T>>.DeepSignalSetProps<T>
Type Parameters
T
T
Properties
__raw__
__raw__:
Set
Defined in: sdk/js/alien-deepsignals/src/types.ts:156
The original raw object.
Inherited from
DeepSignalObjectProps.__raw__
[toStringTag]
readonly[toStringTag]:string
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts:145
Inherited from
Set.[toStringTag]
size
readonlysize:number
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts:112
Returns
the number of (unique) elements in Set.
Inherited from
Set.size
Methods
[dispose]()
Call Signature
[dispose]():
void
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.disposable.d.ts:36
Returns
void
Inherited from
SetIterator.[dispose]
Call Signature
[dispose]():
void
Defined in: node_modules/.pnpm/@types+node@22.18.3/node_modules/@types/node/compatibility/disposable.d.ts:9
Returns
void
Inherited from
SetIterator.[dispose]
[iterator]()
[iterator]():
SetIterator<DeepSignal<T>>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts:198
Iterates over values in the set.
Returns
SetIterator<DeepSignal<T>>
Inherited from
Set.[iterator]
add()
add(
value):this
Defined in: sdk/js/alien-deepsignals/src/types.ts:192
Appends a new element with a specified value to the end of the Set.
Parameters
value
T | DeepSignal<T>
Returns
this
Overrides
Set.add
clear()
clear():
void
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts:95
Returns
void
Inherited from
Set.clear
delete()
delete(
value):boolean
Defined in: sdk/js/alien-deepsignals/src/types.ts:193
Removes a specified value from the Set.
Parameters
value
T | DeepSignal<T>
Returns
boolean
Returns true if an element in the Set existed and has been removed, or false if the element does not exist.
Overrides
Set.delete
difference()
difference<
U>(other):Set<DeepSignal<T>>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts:48
Type Parameters
U
U
Parameters
other
ReadonlySetLike<U>
Returns
Set<DeepSignal<T>>
a new Set containing all the elements in this Set which are not also in the argument.
Inherited from
Set.difference
drop()
drop(
count):IteratorObject<DeepSignal<T>,undefined,unknown>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:74
Creates an iterator whose values are the values from this iterator after skipping the provided count.
Parameters
count
number
The number of values to drop.
Returns
IteratorObject<DeepSignal<T>, undefined, unknown>
Inherited from
SetIterator.drop
entries()
entries():
SetIterator<[DeepSignal<T>,DeepSignal<T>]>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts:203
Returns an iterable of [v,v] pairs for every value v in the set.
Returns
SetIterator<[DeepSignal<T>, DeepSignal<T>]>
Inherited from
Set.entries
every()
every(
predicate):boolean
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:122
Determines whether all the members of this iterator satisfy the specified test.
Parameters
predicate
(value, index) => unknown
A function that accepts up to two arguments. The every method calls the predicate function for each element in this iterator until the predicate returns false, or until the end of this iterator.
Returns
boolean
Inherited from
SetIterator.every
filter()
Call Signature
filter<
S>(predicate):IteratorObject<S,undefined,unknown>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:56
Creates an iterator whose values are those from this iterator for which the provided predicate returns true.
Type Parameters
S
S
Parameters
predicate
(value, index) => value is S
A function that accepts up to two arguments to be used to test values from the underlying iterator.
Returns
IteratorObject<S, undefined, unknown>
Inherited from
SetIterator.filter
Call Signature
filter(
predicate):IteratorObject<DeepSignal<T>,undefined,unknown>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:62
Creates an iterator whose values are those from this iterator for which the provided predicate returns true.
Parameters
predicate
(value, index) => unknown
A function that accepts up to two arguments to be used to test values from the underlying iterator.
Returns
IteratorObject<DeepSignal<T>, undefined, unknown>
Inherited from
SetIterator.filter
find()
Call Signature
find<
S>(predicate):S|undefined
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:131
Returns the value of the first element in this iterator where predicate is true, and undefined otherwise.
Type Parameters
S
S
Parameters
predicate
(value, index) => value is S
find calls predicate once for each element of this iterator, in order, until it finds one where predicate returns true. If such an element is found, find immediately returns that element value. Otherwise, find returns undefined.
Returns
S | undefined
Inherited from
SetIterator.find
Call Signature
find(
predicate):DeepSignal<T> |undefined
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:132
Parameters
predicate
(value, index) => unknown
Returns
DeepSignal<T> | undefined
Inherited from
SetIterator.find
first()
first():
Textendsobject?DeepSignal<T> :T|undefined
Defined in: sdk/js/alien-deepsignals/src/types.ts:164
Get the element that was first inserted into the set.
Returns
T extends object ? DeepSignal<T> : T | undefined
Inherited from
flatMap()
flatMap<
U>(callback):IteratorObject<U,undefined,unknown>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:80
Creates an iterator whose values are the result of applying the callback to the values from this iterator and then flattening the resulting iterators or iterables.
Type Parameters
U
U
Parameters
callback
(value, index) => Iterator<U, unknown, undefined> | Iterable<U, unknown, undefined>
A function that accepts up to two arguments to be used to transform values from the underlying iterator into new iterators or iterables to be flattened into the result.
Returns
IteratorObject<U, undefined, unknown>
Inherited from
SetIterator.flatMap
forEach()
Call Signature
forEach(
callbackfn,thisArg?):void
Defined in: sdk/js/alien-deepsignals/src/types.ts:195
Executes a provided function once per each value in the Set object, in insertion order.
Parameters
callbackfn
(value, value2, set) => void
thisArg?
any
Returns
void
Overrides
Set.forEach
Call Signature
forEach(
callbackfn,thisArg?):void
Defined in: sdk/js/alien-deepsignals/src/types.ts:203
Executes a provided function once per each value in the Set object, in insertion order.
Parameters
callbackfn
(value, index) => void
thisArg?
any
Returns
void
Overrides
Set.forEach
getBy()
getBy(
graphIri,subjectIri):DeepSignal<T> |undefined
Defined in: sdk/js/alien-deepsignals/src/types.ts:180
Retrieve an object from the Set by its @graph and @id.
Parameters
graphIri
string
The @graph NURI of the object.
subjectIri
string
The @subject IRI of the object.
Returns
DeepSignal<T> | undefined
The proxied entry if found, undefined otherwise.
Inherited from
getById()
getById(
id):DeepSignal<T> |undefined
Defined in: sdk/js/alien-deepsignals/src/types.ts:171
Retrieve an entry from the Set by its synthetic set ID.
Parameters
id
The synthetic ID (string or number) assigned to the entry.
string | number
Returns
DeepSignal<T> | undefined
The proxied entry if found, undefined otherwise.
Inherited from
has()
has(
value):boolean
Defined in: sdk/js/alien-deepsignals/src/types.ts:194
Parameters
value
T | DeepSignal<T>
Returns
boolean
a boolean indicating whether an element with the specified value exists in the Set or not.
Overrides
Set.has
intersection()
intersection<
U>(other):Set<DeepSignal<T> &U>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts:44
Type Parameters
U
U
Parameters
other
ReadonlySetLike<U>
Returns
Set<DeepSignal<T> & U>
a new Set containing all the elements which are both in this Set and in the argument.
Inherited from
Set.intersection
isDisjointFrom()
isDisjointFrom(
other):boolean
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts:64
Parameters
other
ReadonlySetLike<unknown>
Returns
boolean
a boolean indicating whether this Set has no elements in common with the argument.
Inherited from
Set.isDisjointFrom
isSubsetOf()
isSubsetOf(
other):boolean
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts:56
Parameters
other
ReadonlySetLike<unknown>
Returns
boolean
a boolean indicating whether all the elements in this Set are also in the argument.
Inherited from
Set.isSubsetOf
isSupersetOf()
isSupersetOf(
other):boolean
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts:60
Parameters
other
ReadonlySetLike<unknown>
Returns
boolean
a boolean indicating whether all the elements in the argument are also in this Set.
Inherited from
Set.isSupersetOf
keys()
keys():
SetIterator<DeepSignal<T>>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts:208
Despite its name, returns an iterable of the values in the set.
Returns
SetIterator<DeepSignal<T>>
Inherited from
Set.keys
map()
map<
U>(callbackfn):IteratorObject<U,undefined,unknown>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:50
Creates an iterator whose values are the result of applying the callback to the values from this iterator.
Type Parameters
U
U
Parameters
callbackfn
(value, index) => U
A function that accepts up to two arguments to be used to transform values from the underlying iterator.
Returns
IteratorObject<U, undefined, unknown>
Inherited from
SetIterator.map
next()
next(…
__namedParameters):IteratorResult<DeepSignal<T>,undefined>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts:43
Parameters
__namedParameters
[] | [unknown]
Returns
IteratorResult<DeepSignal<T>, undefined>
Inherited from
SetIterator.next
reduce()
Call Signature
reduce(
callbackfn):DeepSignal
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:87
Calls the specified callback function for all the elements in this iterator. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
Parameters
callbackfn
(previousValue, currentValue, currentIndex) => DeepSignal
A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the iterator.
Returns
Inherited from
SetIterator.reduce
Call Signature
reduce(
callbackfn,initialValue):DeepSignal
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:88
Parameters
callbackfn
(previousValue, currentValue, currentIndex) => DeepSignal
initialValue
Returns
Inherited from
SetIterator.reduce
Call Signature
reduce<
U>(callbackfn,initialValue):U
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:95
Calls the specified callback function for all the elements in this iterator. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
Type Parameters
U
U
Parameters
callbackfn
(previousValue, currentValue, currentIndex) => U
A function that accepts up to three arguments. The reduce method calls the callbackfn function one time for each element in the iterator.
initialValue
U
If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of a value from the iterator.
Returns
U
Inherited from
SetIterator.reduce
return()?
optionalreturn(value?):IteratorResult<DeepSignal<T>,undefined>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts:44
Parameters
value?
undefined
Returns
IteratorResult<DeepSignal<T>, undefined>
Inherited from
SetIterator.return
some()
some(
predicate):boolean
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:114
Determines whether the specified callback function returns true for any element of this iterator.
Parameters
predicate
(value, index) => unknown
A function that accepts up to two arguments. The some method calls the predicate function for each element in this iterator until the predicate returns a value true, or until the end of the iterator.
Returns
boolean
Inherited from
SetIterator.some
symmetricDifference()
symmetricDifference<
U>(other):Set<DeepSignal<T> |U>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts:52
Type Parameters
U
U
Parameters
other
ReadonlySetLike<U>
Returns
Set<DeepSignal<T> | U>
a new Set containing all the elements which are in either this Set or in the argument, but not in both.
Inherited from
Set.symmetricDifference
take()
take(
limit):IteratorObject<DeepSignal<T>,undefined,unknown>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:68
Creates an iterator whose values are the values from this iterator, stopping once the provided limit is reached.
Parameters
limit
number
The maximum number of values to yield.
Returns
IteratorObject<DeepSignal<T>, undefined, unknown>
Inherited from
SetIterator.take
throw()?
optionalthrow(e?):IteratorResult<DeepSignal<T>,undefined>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts:45
Parameters
e?
any
Returns
IteratorResult<DeepSignal<T>, undefined>
Inherited from
SetIterator.throw
toArray()
toArray():
DeepSignal<T>[]
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts:100
Creates a new array from the values yielded by this iterator.
Returns
DeepSignal<T>[]
Inherited from
SetIterator.toArray
union()
union<
U>(other):Set<DeepSignal<T> |U>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.esnext.collection.d.ts:40
Type Parameters
U
U
Parameters
other
ReadonlySetLike<U>
Returns
Set<DeepSignal<T> | U>
a new Set containing all the elements in this Set and also all the elements in the argument.
Inherited from
Set.union
values()
values():
SetIterator<DeepSignal<T>>
Defined in: node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts:213
Returns an iterable of values in the set.
Returns
SetIterator<DeepSignal<T>>
Inherited from
Set.values
WatchOptions
Defined in: sdk/js/alien-deepsignals/src/watch.ts:27
Properties
immediate?
optionalimmediate:boolean
Defined in: sdk/js/alien-deepsignals/src/watch.ts:29
True, if the callback should be run immediately after watch was called.
Default
false;
once?
optionalonce:boolean
Defined in: sdk/js/alien-deepsignals/src/watch.ts:31
True, if the watcher should be unsubscribed after the first event.
Default
false;
triggerInstantly?
optionaltriggerInstantly:boolean
Defined in: sdk/js/alien-deepsignals/src/watch.ts:38
If true, triggers watch callback instantly after changes to the signal object. Otherwise, changes are batched and the watch callback is triggered in a microtask. This is useful for frontends like React where modifications on the changed input in a separate (microtask) will cause the cursor in input elements to reset.
WatchPatchEvent
Defined in: sdk/js/alien-deepsignals/src/watch.ts:41
Type Parameters
T
T extends object
Properties
newValue
newValue:
DeepSignal<T>
Defined in: sdk/js/alien-deepsignals/src/watch.ts:47
The current value of the signal
patches
patches:
DeepPatch[]
Defined in: sdk/js/alien-deepsignals/src/watch.ts:43
The changes made
version?
optionalversion:number
Defined in: sdk/js/alien-deepsignals/src/watch.ts:45
The version if triggerInstantly is not true.
Type Aliases
ComputedSignal
ComputedSignal<
T> =ReturnType<typeofcomputed>
Defined in: sdk/js/alien-deepsignals/src/types.ts:150
Type Parameters
T
T = any
DeepPatch
DeepPatch =
object& {op:"add";type?:"object"|"set";value?:any; } | {op:"remove";type?:"set";value?:any; }
Defined in: sdk/js/alien-deepsignals/src/types.ts:15
Deep mutation emitted from a deepSignal root.
Type Declaration
path
path: (
string|number)[]
DeepSignal
DeepSignal<
T> =TextendsFunction?T:Textendsstring|number|boolean?T:TextendsDeepSignalObjectProps<any> |DeepSignalObjectProps<any>[] ?T:Textends infer I[] ?DeepSignal<I>[] :TextendsSet<infer S> ?DeepSignalSet<S> :Textendsobject?DeepSignalObject<T> :T
Defined in: sdk/js/alien-deepsignals/src/types.ts:214
The object returned by the deepSignal function.
It is decorated with utility functions for sets, see DeepSignalSetProps
and a __raw__ prop to get the underlying non-reactive object.
Type Parameters
T
T
DeepSignalObject
DeepSignalObject<
T> ={ [K in keyof T]: DeepSignal<T[K]> }
Defined in: sdk/js/alien-deepsignals/src/types.ts:228
Type Parameters
T
T extends object
DeepSignalPropGenFn()
DeepSignalPropGenFn = (
props) =>object
Defined in: sdk/js/alien-deepsignals/src/types.ts:106
Internal
The propGenerator function is called when a new object is added to the deep signal tree.
Parameters
props
inSet
boolean
Whether the object is being added to a Set (true) or not (false)
object
any
The newly added object itself
path
(string | number)[]
The path of the newly added object.
Returns
extraProps?
optionalextraProps:Record<string,unknown>
Additional properties to be added to the object (overwriting existing ones).
syntheticId?
optionalsyntheticId:string|number
A custom identifier for the object (used in Set entry paths and optionally as a property).
Example
let counter = 0;
const state = deepSignal(
{ items: new Set() },
{
propGenerator: ({ path, inSet, object }) => ({
syntheticId: inSet
? `urn:item:${++counter}`
: `urn:obj:${path.join("-")}`,
extraProps: { createdAt: new Date().toISOString() },
}),
syntheticIdPropertyName: "@id",
},
);
state.items.add({ name: "Item 1" });
// Attaches `{ name: "Item 1", `@id`: "urn:item:1", createdAt: <current date>`
state.foo = { bar: 42 };
// Attaches `{bar: 42, "@id": "urn:obj:foo", createdAt: <current date>}`
DeepSignalSetProps
DeepSignalSetProps<
T> =object
Defined in: sdk/js/alien-deepsignals/src/types.ts:162
Utility functions for sets.
Extended by
Type Parameters
T
T
Methods
first()
first():
Textendsobject?DeepSignal<T> :T|undefined
Defined in: sdk/js/alien-deepsignals/src/types.ts:164
Get the element that was first inserted into the set.
Returns
T extends object ? DeepSignal<T> : T | undefined
getBy()
getBy(
graphIri,subjectIri):DeepSignal<T> |undefined
Defined in: sdk/js/alien-deepsignals/src/types.ts:180
Retrieve an object from the Set by its @graph and @id.
Parameters
graphIri
string
The @graph NURI of the object.
subjectIri
string
The @subject IRI of the object.
Returns
DeepSignal<T> | undefined
The proxied entry if found, undefined otherwise.
getById()
getById(
id):DeepSignal<T> |undefined
Defined in: sdk/js/alien-deepsignals/src/types.ts:171
Retrieve an entry from the Set by its synthetic set ID.
Parameters
id
The synthetic ID (string or number) assigned to the entry.
string | number
Returns
DeepSignal<T> | undefined
The proxied entry if found, undefined otherwise.
ExternalSubscriberFactory()
ExternalSubscriberFactory<
T> = () =>object
Defined in: sdk/js/alien-deepsignals/src/types.ts:74
Type Parameters
T
T = any
Returns
object
onGet()
onGet: () =>
void
Returns
void
onSet()
onSet: (
newVal) =>void
Parameters
newVal
T
Returns
void
MaybeSignal
MaybeSignal<
T> =T|ReturnType<typeofalienSignal>
Defined in: sdk/js/alien-deepsignals/src/types.ts:235
Union allowing a plain value or a writable signal wrapping that value.
Type Parameters
T
T = any
MaybeSignalOrComputed
MaybeSignalOrComputed<
T> =MaybeSignal<T> | () =>T
Defined in: sdk/js/alien-deepsignals/src/types.ts:237
Union allowing value, writable signal, computed signal or plain getter function.
Type Parameters
T
T = any
RegisterCleanup()
RegisterCleanup = (
cleanupFn) =>void
Defined in: sdk/js/alien-deepsignals/src/watch.ts:25
Parameters
cleanupFn
() => void
Returns
void
SignalLike
SignalLike<
T> =WritableSignal<T> |ComputedSignal<T>
Defined in: sdk/js/alien-deepsignals/src/types.ts:151
Type Parameters
T
T = any
UnwrapDeepSignal
UnwrapDeepSignal<
T> =TextendsDeepSignal<infer S> ?S:T
Defined in: sdk/js/alien-deepsignals/src/types.ts:232
Type Parameters
T
T
WatchPatchCallback()
WatchPatchCallback<
T> = (event) =>void
Defined in: sdk/js/alien-deepsignals/src/watch.ts:50
Type Parameters
T
T extends object
Parameters
event
Returns
void
Variables
alienSignal()
constalienSignal: {<T>(): {():T|undefined; (value):void; }; <T>(initialValue): {():T; (value):void; }; } =alienSignal_
Defined in: sdk/js/alien-deepsignals/src/core.ts:99
Re-export of alien-signals signal function which creates a basic signal.
Call Signature
<
T>(): {():T|undefined; (value):void; }
Type Parameters
T
T
Returns
():
T|undefined
Returns
T | undefined
(
value):void
Parameters
value
T | undefined
Returns
void
Call Signature
<
T>(initialValue): {():T; (value):void; }
Type Parameters
T
T
Parameters
initialValue
T
Returns
():
T
Returns
T
(
value):void
Parameters
value
T
Returns
void
computed()
constcomputed: <T>(getter) => () =>T=alienComputed
Defined in: sdk/js/alien-deepsignals/src/core.ts:94
Re-export of alien-signals computed function.
Use the computed() function to create lazy derived signals that automatically
track their dependencies and recompute only when needed.
Key features:
- Lazy evaluation: The computation runs only when you actually read the computed value.
If you never access
fullName(), the concatenation never happens—no wasted CPU cycles. - Automatic caching: Once computed, the result is cached until a dependency changes. Multiple reads return the cached value without re-running the getter.
- Fine-grained reactivity: Only recomputes when its tracked dependencies change. Unrelated state mutations don’t trigger unnecessary recalculation.
- Composable: Computed signals can depend on other computed signals, forming efficient dependency chains.
Type Parameters
T
T
Parameters
getter
(previousValue?) => T
Returns
():
T
Returns
T
Example
import { computed } from "@ng-org/alien-deepsignals";
const state = deepSignal({
firstName: "Ada",
lastName: "Lovelace",
items: [1, 2, 3],
});
// Create a computed signal that derives from reactive state
const fullName = computed(() => `${state.firstName} ${state.lastName}`);
console.log(fullName()); // "Ada Lovelace" - computes on first access
state.firstName = "Grace";
console.log(fullName()); // "Grace Lovelace" - recomputes automatically
// Expensive computation only runs when accessed and dependencies change
const expensiveResult = computed(() => {
console.log("Computing...");
return state.items.reduce((sum, n) => sum + n * n, 0);
});
// No computation happens yet!
state.items.push(4);
// Still no computation...
console.log(expensiveResult()); // "Computing..." + result
console.log(expensiveResult()); // Cached, no log
state.items.push(5);
console.log(expensiveResult()); // "Computing..." again (dependency changed)
effect()
consteffect: (fn) => () =>void=alienEffect
Defined in: sdk/js/alien-deepsignals/src/core.ts:107
Re-export of alien-signals effect function.
Callback reruns on every signal modification that is used within its callback.
Parameters
fn
() => void
Returns
():
void
Returns
void
Functions
addWithId()
addWithId<
T>(set,entry,id):T
Defined in: sdk/js/alien-deepsignals/src/deepSignal.ts:1439
Convenience helper to add an entry to a proxied Set with a pre-defined synthetic ID.
Type Parameters
T
T
Parameters
set
Set<T>
entry
T
id
string | number
Returns
T
batch()
batch<
T>(fn):T
Defined in: sdk/js/alien-deepsignals/src/core.ts:34
Execute multiple signal writes in a single batched update frame. All downstream computed/effect re-evaluations are deferred until the function exits.
IMPORTANT: The callback must be synchronous. If it returns a Promise the batch will still end immediately after scheduling, possibly causing mid-async flushes.
Type Parameters
T
T
Parameters
fn
() => T
Returns
T
Example
batch(() => {
count(count() + 1);
other(other() + 2);
}); // effects observing both run only once
deepSignal()
deepSignal<
T>(input,options?):DeepSignal<T>
Defined in: sdk/js/alien-deepsignals/src/deepSignal.ts:1328
MAIN ENTRY POINT to create a deep reactive proxy for objects, arrays or Sets.
If input is a deepSignal already and options are provided,
the added subscriberFactories are joined with the existing ones
and replaceProxiesInBranchOnChange is or-ed with the current value.
Type Parameters
T
T extends object
Parameters
input
T
options?
Returns
DeepSignal<T>
Throws
if provided with unsupported input types.
getRaw()
getRaw<
T>(value):any
Defined in: sdk/js/alien-deepsignals/src/deepSignal.ts:1455
Get the original, raw value of a deep signal.
Type Parameters
T
T extends object
Parameters
value
T | DeepSignal<T>
Returns
any
isDeepSignal()
isDeepSignal(
value):value is any
Defined in: sdk/js/alien-deepsignals/src/deepSignal.ts:1314
Runtime guard that checks whether a value is a deepSignal proxy.
Parameters
value
unknown
Returns
value is any
shallow()
shallow<
T>(obj):T
Defined in: sdk/js/alien-deepsignals/src/deepSignal.ts:1426
Mark an object so deepSignal skips proxying it (shallow boundary).
Type Parameters
T
T extends object
Parameters
obj
T
Returns
T
Example
import { shallow } from "alien-deepsignals";
state.config = shallow({ huge: { blob: true } });
subscribeDeepMutations()
subscribeDeepMutations(
root,cb,triggerInstantly?): () =>void
Defined in: sdk/js/alien-deepsignals/src/deepSignal.ts:1378
Low-level function, you should probably use watch instead.
Register a deep mutation subscriber for the provided root or proxy.
Parameters
root
symbol | object
cb
DeepPatchJITSubscriber | DeepPatchSubscriber
triggerInstantly?
boolean = false
Returns
():
void
Returns
void
watch()
watch<
T>(source,callback,options?):object
Defined in: sdk/js/alien-deepsignals/src/watch.ts:89
Watch for changes to a deepSignal.
Whenever a change is made, callback is called with the patches describing the change and the new value.
If you set triggerInstantly, the callback is called on every property change.
If not, all changes are aggregated and callback is called in a microtask when
the current task finishes, e.g. await is called (meaning it supports batching).
When objects are added to Sets, their synthetic ID (usually @id) becomes part of the patch path. This allows patches to uniquely identify which Set entry is being mutated.
const state = deepSignal(
{ s: new Set() },
{ ...}
);
watch(state, ({ patches }) => {
console.log(JSON.stringify(patches));
});
state.s.add({ data: "test" });
// Will log:
// [
// {"path":["s","did:ng:o:123"],"op":"add","type":"object"},
// {"path":["s","did:ng:o:123","@id"],"op":"add","value":"did:ng:o:123"},
// {"path":["s","did:ng:o:123","data"],"op":"add","value":"test"}
// ]
state.s.getById("did:ng:o:123")!.data = "new value"
// Will log:
// [
// {"path":["s","did:ng:o:123","data"],"op":"add","value":"new value"}
// ]
Type Parameters
T
T extends object
Parameters
source
DeepSignalSet<T> | DeepSignalObject<T> | DeepSignal<T>
callback
options?
WatchOptions = {}
Returns
object
registerCleanup
registerCleanup:
RegisterCleanup
stopListening()
stopListening: () =>
void
Returns
void