Abstract
Protected
Abstract
deriveProtected
equalCompares two values and returns true if they are equal. +
Abstract
Base class that can be extended to easily create a custom Readable store.
+class CounterStore extends Store {
constructor() {
super(1); // initial value
}
reset() {
this.set(0);
}
increment() {
this.update(value => value + 1);
}
}
const store = new CounterStore(1);
// logs 1 (initial value) upon subscription
const unsubscribe = store.subscribe((value) => {
console.log(value);
});
store.increment(); // logs 2
store.reset(); // logs 0
unsubscribe(); // stops notifications and corresponding logging
+
+
+Protected
Abstract
deriveProtected
equalCompares two values and returns true if they are equal.
It is called when setting a new value to avoid doing anything
(such as notifying subscribers) if the value did not change.
The default logic is to return false if a
is a function or an object,
or if a
and b
are different according to Object.is
.
This method can be overridden by subclasses to change the logic.
First value to compare.
-Second value to compare.
+true if a and b are considered equal.
-For backward compatibility, the default implementation calls the +
For backward compatibility, the default implementation calls the deprecated Store.notEqual method and returns the negation of its return value.
-Protected
notProtected
notCompares two values and returns true if they are different.
It is called when setting a new value to avoid doing anything
(such as notifying subscribers) if the value did not change.
The default logic is to return true if a
is a function or an object,
or if a
and b
are different according to Object.is
.
This method can be overridden by subclasses to change the logic.
First value to compare.
-Second value to compare.
+true if a and b are considered different.
-This method is only called by the default implementation of +
This method is only called by the default implementation of Store.equal, so overriding Store.equal takes precedence over overriding notEqual.
-Use Store.equal instead
-Protected
onFunction called when the number of subscribers changes from 0 to 1 +
Use Store.equal instead
+Protected
Optional
onFunction called when the number of subscribers changes from 0 to 1 (but not called when the number of subscribers changes from 1 to 2, ...). If a function is returned, it will be called when the number of subscribers changes from 1 to 0.
-class CustomStore extends Store {
onUse() {
console.log('Got the fist subscriber!');
return () => {
console.log('All subscribers are gone...');
};
}
}
const store = new CustomStore();
const unsubscribe1 = store.subscribe(() => {}); // logs 'Got the fist subscriber!'
const unsubscribe2 = store.subscribe(() => {}); // nothing is logged as we've got one subscriber already
unsubscribe1(); // nothing is logged as we still have one subscriber
unsubscribe2(); // logs 'All subscribers are gone...'
-
-Protected
pausePuts the store in the paused state, which means it will soon update its value.
-The paused state prevents derived or computed stores (both direct and transitive) from recomputing their value -using the current value of this store.
-There are two ways to put a store back into its normal state: calling set to set a new -value or calling resumeSubscribers to declare that finally the value does not need to be -changed.
-Note that a store should not stay in the paused state for a long time, and most of the time -it is not needed to call pauseSubscribers or resumeSubscribers manually.
-Protected
resumePuts the store back to the normal state without changing its value, if it was in the paused state -(cf pauseSubscribers).
-Does nothing if the store was not in the paused state.
-Protected
setReplaces store's state with the provided value. +
class CustomStore extends Store {
onUse() {
console.log('Got the fist subscriber!');
return () => {
console.log('All subscribers are gone...');
};
}
}
const store = new CustomStore();
const unsubscribe1 = store.subscribe(() => {}); // logs 'Got the fist subscriber!'
const unsubscribe2 = store.subscribe(() => {}); // nothing is logged as we've got one subscriber already
unsubscribe1(); // nothing is logged as we still have one subscriber
unsubscribe2(); // logs 'All subscribers are gone...'
+
+
+Protected
setReplaces store's state with the provided value. Equivalent of Writable.set, but internal to the store.
-value to be used as the new state of a store.
-Default Implementation of the SubscribableStore.subscribe, not meant to be overridden.
-Protected
updateDefault Implementation of the SubscribableStore.subscribe, not meant to be overridden.
+Protected
updateUpdates store's state by using an Updater function. Equivalent of Writable.update, but internal to the store.
-Generated using TypeDoc
Abstract
Base class that can be extended to easily create a custom Readable store.
-class CounterStore extends Store {
constructor() {
super(1); // initial value
}
reset() {
this.set(0);
}
increment() {
this.update(value => value + 1);
}
}
const store = new CounterStore(1);
// logs 1 (initial value) upon subscription
const unsubscribe = store.subscribe((value) => {
console.log(value);
});
store.increment(); // logs 2
store.reset(); // logs 0
unsubscribe(); // stops notifications and corresponding logging
-
-Protected
equalCompares two values and returns true if they are equal. +
Abstract
Base class that can be extended to easily create a custom Readable store.
+class CounterStore extends Store {
constructor() {
super(1); // initial value
}
reset() {
this.set(0);
}
increment() {
this.update(value => value + 1);
}
}
const store = new CounterStore(1);
// logs 1 (initial value) upon subscription
const unsubscribe = store.subscribe((value) => {
console.log(value);
});
store.increment(); // logs 2
store.reset(); // logs 0
unsubscribe(); // stops notifications and corresponding logging
+
+
+Protected
equalCompares two values and returns true if they are equal.
It is called when setting a new value to avoid doing anything
(such as notifying subscribers) if the value did not change.
The default logic is to return false if a
is a function or an object,
or if a
and b
are different according to Object.is
.
This method can be overridden by subclasses to change the logic.
First value to compare.
-Second value to compare.
+true if a and b are considered equal.
-For backward compatibility, the default implementation calls the +
For backward compatibility, the default implementation calls the deprecated Store.notEqual method and returns the negation of its return value.
-Protected
notProtected
notCompares two values and returns true if they are different.
It is called when setting a new value to avoid doing anything
(such as notifying subscribers) if the value did not change.
The default logic is to return true if a
is a function or an object,
or if a
and b
are different according to Object.is
.
This method can be overridden by subclasses to change the logic.
First value to compare.
-Second value to compare.
+true if a and b are considered different.
-This method is only called by the default implementation of +
This method is only called by the default implementation of Store.equal, so overriding Store.equal takes precedence over overriding notEqual.
-Use Store.equal instead
-Protected
onFunction called when the number of subscribers changes from 0 to 1 +
Use Store.equal instead
+Protected
Optional
onFunction called when the number of subscribers changes from 0 to 1 (but not called when the number of subscribers changes from 1 to 2, ...). If a function is returned, it will be called when the number of subscribers changes from 1 to 0.
-class CustomStore extends Store {
onUse() {
console.log('Got the fist subscriber!');
return () => {
console.log('All subscribers are gone...');
};
}
}
const store = new CustomStore();
const unsubscribe1 = store.subscribe(() => {}); // logs 'Got the fist subscriber!'
const unsubscribe2 = store.subscribe(() => {}); // nothing is logged as we've got one subscriber already
unsubscribe1(); // nothing is logged as we still have one subscriber
unsubscribe2(); // logs 'All subscribers are gone...'
-
-Protected
pausePuts the store in the paused state, which means it will soon update its value.
-The paused state prevents derived or computed stores (both direct and transitive) from recomputing their value -using the current value of this store.
-There are two ways to put a store back into its normal state: calling set to set a new -value or calling resumeSubscribers to declare that finally the value does not need to be -changed.
-Note that a store should not stay in the paused state for a long time, and most of the time -it is not needed to call pauseSubscribers or resumeSubscribers manually.
-Protected
resumePuts the store back to the normal state without changing its value, if it was in the paused state -(cf pauseSubscribers).
-Does nothing if the store was not in the paused state.
-Protected
setReplaces store's state with the provided value. +
class CustomStore extends Store {
onUse() {
console.log('Got the fist subscriber!');
return () => {
console.log('All subscribers are gone...');
};
}
}
const store = new CustomStore();
const unsubscribe1 = store.subscribe(() => {}); // logs 'Got the fist subscriber!'
const unsubscribe2 = store.subscribe(() => {}); // nothing is logged as we've got one subscriber already
unsubscribe1(); // nothing is logged as we still have one subscriber
unsubscribe2(); // logs 'All subscribers are gone...'
+
+
+Protected
setReplaces store's state with the provided value. Equivalent of Writable.set, but internal to the store.
-value to be used as the new state of a store.
-Default Implementation of the SubscribableStore.subscribe, not meant to be overridden.
-Protected
updateDefault Implementation of the SubscribableStore.subscribe, not meant to be overridden.
+Protected
updateUpdates store's state by using an Updater function. Equivalent of Writable.update, but internal to the store.
-Generated using TypeDoc
Returns a wrapper (for the given store) which only exposes the ReadableSignal interface. +
Returns a wrapper (for the given store) which only exposes the ReadableSignal interface. This converts any StoreInput to a ReadableSignal and exposes the store as read-only.
-store to wrap
+store to wrap
A wrapper which only exposes the ReadableSignal interface.
-Returns a wrapper (for the given store) which only exposes the ReadableSignal interface and +
Returns a wrapper (for the given store) which only exposes the ReadableSignal interface and also adds the given extra properties on the returned object.
-store to wrap
-extra properties to add on the returned object
+store to wrap
+extra properties to add on the returned object
A wrapper which only exposes the ReadableSignal interface and the given extra properties.
-Generated using TypeDoc
Returns a wrapper (for the given store) which only exposes the WritableSignal interface. +
Returns a wrapper (for the given store) which only exposes the WritableSignal interface. When the value is changed from the given wrapper, the provided set function is called.
-store to wrap
-Optional
set: ((value) => void)function that will be called when the value is changed from the wrapper +
store to wrap
+Optional
set: ((value: W) => void)function that will be called when the value is changed from the wrapper (through the set or the update function). If set is not specified, a noop function is used (so the value of the store cannot be changed from the returned wrapper).
-Replaces store's state with the provided value.
-A wrapper which only exposes the WritableSignal interface.
-Returns a wrapper (for the given store) which only exposes the WritableSignal interface and +
Returns a wrapper (for the given store) which only exposes the WritableSignal interface and also adds the given extra properties on the returned object.
-store to wrap
-object containing the extra properties to add on the returned object, +
store to wrap
+object containing the extra properties to add on the returned object, and optionally the set and the update function of the WritableSignal interface. If the set function is not specified, a noop function is used.
If the update function is not specified, a default function that calls set is used.
A wrapper which only exposes the WritableSignal interface and the given extra properties.
-Generated using TypeDoc
Batches multiple changes to stores while calling the provided function, +
Batches multiple changes to stores while calling the provided function, preventing derived stores from updating until the function returns, to avoid unnecessary recomputations.
-If a store is updated multiple times in the provided function, existing +
If a store is updated multiple times in the provided function, existing subscribers of that store will only be called once when the provided function returns.
Note that even though the computation of derived stores is delayed in most @@ -16,7 +14,10 @@ intermediate computations, even inside batch.
It is possible to have nested calls of batch, in which case only the first (outer) call has an effect, inner calls only call the provided function.
-Using batch in the following example prevents logging the intermediate "Sherlock Lupin" value.
-const firstName = writable('Arsène');
const lastName = writable('Lupin');
const fullName = derived([firstName, lastName], ([a, b]) => `${a} ${b}`);
fullName.subscribe((name) => console.log(name)); // logs any change to fullName
batch(() => {
firstName.set('Sherlock');
lastName.set('Holmes');
});
-
-Generated using TypeDoc
Using batch in the following example prevents logging the intermediate "Sherlock Lupin" value.
+const firstName = writable('Arsène');
const lastName = writable('Lupin');
const fullName = derived([firstName, lastName], ([a, b]) => `${a} ${b}`);
fullName.subscribe((name) => console.log(name)); // logs any change to fullName
batch(() => {
firstName.set('Sherlock');
lastName.set('Holmes');
});
+
+
+Creates a store whose value is computed by the provided function.
-computation function that returns the value of the store
-store option. Allows to define the equal function, if needed
+Creates a store whose value is computed by the provided function.
+store containing the value returned by the computation function
-The computation function is first called the first time the store is used.
+The computation function is first called the first time the store is used.
It can use the value of other stores or observables and the computation function is called again if the value of those dependencies changed, as long as the store is still used.
Dependencies are detected automatically as the computation function gets their value either by calling the stores @@ -11,4 +11,4 @@ to wrap them in a call to untrack.
Note that dependencies can change between calls of the computation function. Internally, tansu will subscribe to new dependencies when they are used and unsubscribe from dependencies that are no longer used after the call of the computation function.
-Generated using TypeDoc
A convenience function to create a new store with a state computed from the latest values of dependent stores. +
A convenience function to create a new store with a state computed from the latest values of dependent stores. Each time the state of one of the dependent stores changes, a provided derive function is called to compute a new, derived state.
-a single store or an array of dependent stores
-either an object with store options, including a derive function, or the derive function itself directly. +
a single store or an array of dependent stores
+either an object with store options, including a derive function, or the derive function itself directly. The derive function is used to compute a new state based on the latest values of dependent stores.
Alternatively, this function can accept a second argument, set
, to manage asynchronous values.
If you return a function from the callback, it will be called when the callback runs again, or the last subscriber unsubscribes.
const x$ = writable(2);
const y$ = writable(3);
const sum$ = derived([x$, $y], ([x, y]) => x + y);
// will log 5 upon subscription
sum$.subscribe((value) => {
console.log(value)
});
x$.set(3); // will re-evaluate the `([x, y]) => x + y` function and log 6 as this is the new state of the derived store
-
-const x$ = writable(2);
const y$ = writable(3);
const sum$ = derived([x$, $y], ([x, y], set) => {
const timeoutId = setTimeout(() => set(x + y)));
return () => clearTimeout(timeoutId);
}, <number>undefined);
// will log undefined (the default value), then 5 asynchronously
sum$.subscribe((value) => {
console.log(value)
});
-
-Optional
initialValue: TGenerated using TypeDoc
const x$ = writable(2);
const y$ = writable(3);
const sum$ = derived([x$, y$], ([x, y]) => x + y);
// will log 5 upon subscription
sum$.subscribe((value) => {
console.log(value)
});
x$.set(3); // will re-evaluate the `([x, y]) => x + y` function and log 6 as this is the new state of the derived store
+
+
+const x$ = writable(2);
const y$ = writable(3);
const sum$ = derived([x$, $y], ([x, y], set) => {
const timeoutId = setTimeout(() => set(x + y)));
return () => clearTimeout(timeoutId);
}, <number>undefined);
// will log undefined (the default value), then 5 asynchronously
sum$.subscribe((value) => {
console.log(value)
});
+
+
+Optional
initialValue: TDefault implementation of the equal function used by tansu when a store +
Default implementation of the equal function used by tansu when a store
changes, to know if listeners need to be notified.
Returns false if a
is a function or an object, or if a
and b
are different according to Object.is
. Otherwise, returns true.
Generated using TypeDoc
A utility function to get the current value from a given store. +
A utility function to get the current value from a given store. It works by subscribing to a store, capturing the value (synchronously) and unsubscribing just after.
-a store from which the current value is retrieved.
-const myStore = writable(1);
console.log(get(myStore)); // logs 1
-
-Generated using TypeDoc
a store from which the current value is retrieved.
+A convenience function to create Readable store instances.
-Initial value of a readable store.
-Either an object with store options, or directly the onUse function.
+A convenience function to create Readable store instances.
+Initial value of a readable store.
+Optional
options: StoreOptions<T> | OnUseFn<T>Either an object with store options, or directly the onUse function.
The onUse function is a function called when the number of subscribers changes from 0 to 1 (but not called when the number of subscribers changes from 1 to 2, ...).
If a function is returned, it will be called when the number of subscribers changes from 1 to 0.
-const clock = readable("00:00", setState => {
const intervalID = setInterval(() => {
const date = new Date();
setState(`${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`);
}, 1000);
return () => clearInterval(intervalID);
});
-
-Generated using TypeDoc
Stops the tracking of dependencies made by computed and calls the provided function. +
A convenience function to create Writable store instances.
-initial value of a new writable store.
-Either an object with store options, or directly the onUse function.
+A convenience function to create Writable store instances.
+initial value of a new writable store.
+Optional
options: StoreOptions<T> | OnUseFn<T>Either an object with store options, or directly the onUse function.
The onUse function is a function called when the number of subscribers changes from 0 to 1 (but not called when the number of subscribers changes from 1 to 2, ...).
If a function is returned, it will be called when the number of subscribers changes from 1 to 0.
-const x = writable(0);
x.update(v => v + 1); // increment
x.set(0); // reset back to the default value
-
-Generated using TypeDoc
Generated using TypeDoc
Tansu is a lightweight, push-based framework-agnostic state management library.
-It borrows the ideas and APIs originally designed and implemented by Svelte stores
+It borrows the ideas and APIs originally designed and implemented by Svelte stores
and extends them with computed
and batch
.
Main characteristics:
Implementation wise, it is a tiny (1300 LOC) library without any external dependencies.
-You can add Tansu to your project by installing the @amadeus-it-group/tansu
package using your favorite package manager, ex.:
You can add Tansu to your project by installing the @amadeus-it-group/tansu
package using your favorite package manager, ex.:
yarn add @amadeus-it-group/tansu
npm install @amadeus-it-group/tansu
Check out the Tansu API documentation.
+Check out the Tansu API documentation.
The functional part of the API to manage your reactive state can be categorized into three distinct groups:
writable
derived
, computed
, readable
batch
, asReadable
, asWritable
Writable: A Fundamental Building Block
A writable
serves as the foundational element of a "store" – a container designed to encapsulate a value, enabling observation and modification of its state. You can change the internal value using the set
or update
methods.
To receive notifications whenever the value undergoes a change, the subscribe()
method, paired with a callback function, can be employed.
import {writable} from "@amadeus-it-group/tansu";
const value$ = writable(0);
const unsubscribe = values$.subscribe((value) => {
console.log(`value = ${value}`);
});
value$.set(1);
value$.update((value) => value + 1);
-
+import {writable} from "@amadeus-it-group/tansu";
const value$ = writable(0);
const unsubscribe = values$.subscribe((value) => {
console.log(`value = ${value}`);
});
value$.set(1);
value$.update((value) => value + 1);
+
+
output:
- value = 0
+ value = 0
value = 1
value = 2
-
-Setup and teardown
The writable's second parameter allows for receiving notifications when at least one subscriber subscribes or when there are no more subscribers.
-import {writable} from "@amadeus-it-group/tansu";
const value$ = writable(0, () => {
console.log('At least one subscriber');
return () => {
console.log('No more subscriber');
}
});
const unsubscribe = values$.subscribe((value) => {
console.log(`value = ${value}`);
});
value$.set(1);
unsubscribe();
-
+
+
+The writable's second parameter allows for receiving notifications when at least one subscriber subscribes or when there are no more subscribers.
+import {writable} from "@amadeus-it-group/tansu";
const value$ = writable(0, () => {
console.log('At least one subscriber');
return () => {
console.log('No more subscriber');
}
});
const unsubscribe = values$.subscribe((value) => {
console.log(`value = ${value}`);
});
value$.set(1);
unsubscribe();
+
+
output:
- At least one subscriber
+ At least one subscriber
value = 0
value = 1
No more subscriber
-
-derived
+
+
+A derived
store calculates its value based on one or more other stores provided as parameters.
Since its value is derived from other stores, it is a read-only store and does not have any set
or update
methods.
import {writable, derived} from "@amadeus-it-group/tansu";
const value$ = writable(1);
const double$ = derived(value$, (value) => value * 2);
double$.subscribe((double) => console.log('Double value', double));
value$.set(2);
-
+import {writable, derived} from "@amadeus-it-group/tansu";
const value$ = writable(1);
const double$ = derived(value$, (value) => value * 2);
double$.subscribe((double) => console.log('Double value', double));
value$.set(2);
+
+
output:
-Double value 2
+Double value 2
Double value 4
-
-Multiple stores
import {writable, derived} from "@amadeus-it-group/tansu";
const a$ = writable(1);
const b$ = writable(1);
const sum$ = derived([a$, b$], ([a, b]) => a + b);
sum$.subscribe((sum) => console.log('Sum', sum));
a$.set(2);
-
+
+
+import {writable, derived} from "@amadeus-it-group/tansu";
const a$ = writable(1);
const b$ = writable(1);
const sum$ = derived([a$, b$], ([a, b]) => a + b);
sum$.subscribe((sum) => console.log('Sum', sum));
a$.set(2);
+
+
output:
-Sum 2
+Sum 2
Sum 3
-
-Asynchronous set
A derived
can directly manipulate its value using the set method instead of relying on the returned value of the provided function.
-This flexibility allows you to manage asynchronous operations or apply filtering logic before updating the observable's value.
-import {writable, derived} from "@amadeus-it-group/tansu";
const a$ = writable(0);
const asynchronousDouble$ = derived(a$, (a, set) => {
const plannedLater = setTimeout(() => set(a * 2));
return () => {
// This clean-up function is called if there is no listener anymore,
// or if the value of a$ changed
// In this case, the function passed to setTimeout should not be called
// (if it was not called already)
clearTimeout(plannedLater);
};
}, -1);
const evenOnly$ = derived(a$, (a, set) => {
if (a % 2 === 0) {
set(a);
}
}, <number | undefined>undefined);
asynchronousDouble$.subscribe((double) => console.log('Double (asynchronous)', double));
evenOnly$.subscribe((value) => console.log('Even', value));
a$.set(1);
a$.set(2);
-
+
+
+A derived
can directly manipulate its value using the set method instead of relying on the returned value of the provided function.
+This flexibility allows you to manage asynchronous operations or apply filtering logic before updating the observable's value.
import {writable, derived} from "@amadeus-it-group/tansu";
const a$ = writable(0);
const asynchronousDouble$ = derived(a$, (a, set) => {
const plannedLater = setTimeout(() => set(a * 2));
return () => {
// This clean-up function is called if there is no listener anymore,
// or if the value of a$ changed
// In this case, the function passed to setTimeout should not be called
// (if it was not called already)
clearTimeout(plannedLater);
};
}, -1);
const evenOnly$ = derived(a$, (a, set) => {
if (a % 2 === 0) {
set(a);
}
}, <number | undefined>undefined);
asynchronousDouble$.subscribe((double) => console.log('Double (asynchronous)', double));
evenOnly$.subscribe((value) => console.log('Even', value));
a$.set(1);
a$.set(2);
+
+
output:
-Double (asynchronous) -1
+Double (asynchronous) -1
Even 0
Even 2
Double (asynchronous) 4
-
-computed
+
+
+A computed
store is another variant of a derived store, with the following characteristics:
Implicit Dependencies: Unlike in a derived store, there is no requirement to explicitly declare dependencies.
+Implicit Dependencies: Unlike in a derived store, there is no requirement to explicitly declare dependencies.
Dynamic Dependency Listening: Dependencies are determined based on their usage. This implies that a dependency not actively used is not automatically "listened" to, optimizing resource utilization.
+Dynamic Dependency Listening: Dependencies are determined based on their usage. This implies that a dependency not actively used is not automatically "listened" to, optimizing resource utilization.
This capability to subscribe/unsubscribe to the dependency allows to create switch maps in a natural way.
-import {writable, computed} from "@amadeus-it-group/tansu";
const switchToA$ = writable(true);
const a$ = writable(1);
const b$ = writable(0);
const computedValue$ = computed(() => {
if (switchToA$()) {
console.log('Return a$');
return a$();
} else {
console.log('Return b$');
return b$();
}
});
computedValue$.subscribe((value) => console.log('Computed value:', value));
a$.set(2);
switchToA$.set(false);
a$.set(3);
a$.set(4);
switchToA$.set(true);
-
+This capability to subscribe/unsubscribe to the dependency allows to create switch maps in a natural way.
+import {writable, computed} from "@amadeus-it-group/tansu";
const switchToA$ = writable(true);
const a$ = writable(1);
const b$ = writable(0);
const computedValue$ = computed(() => {
if (switchToA$()) {
console.log('Return a$');
return a$();
} else {
console.log('Return b$');
return b$();
}
});
computedValue$.subscribe((value) => console.log('Computed value:', value));
a$.set(2);
switchToA$.set(false);
a$.set(3);
a$.set(4);
switchToA$.set(true);
+
+
output:
-Return a$
+Return a$
Computed value: 1
Return a$
Computed value: 2
@@ -89,51 +102,59 @@
Computed value: 0
Return a$
Computed value: 4
-
+
+
When switchToA$.set(false)
is called, the subscription to a$
is canceled, which means that subsequent changes to a$
will no longer trigger the calculation., which is only performed again when switchToA$ is set back to true.
Similar to Svelte stores, this function generates a store where the value cannot be externally modified.
-import {readable} from '@amadeus-it-group/tansu';
const time = readable(new Date(), (set) => {
const interval = setInterval(() => {
set(new Date());
}, 1000);
return () => clearInterval(interval);
});
-
-While derived and computed may appear similar, they exhibit distinct characteristics that can significantly impact effectiveness based on use-cases:
+import {readable} from '@amadeus-it-group/tansu';
const time = readable(new Date(), (set) => {
const interval = setInterval(() => {
set(new Date());
}, 1000);
return () => clearInterval(interval);
});
+
+
+While derived and computed may appear similar, they exhibit distinct characteristics that can significantly impact effectiveness based on use-cases:
Declaration of Dependencies:
+Declaration of Dependencies:
computed
: No explicit declaration of dependencies is required, providing more flexibility in code composition.derived
: Requires explicit declaration of dependencies.Performance:
+Performance:
computed
: Better performance by re-running the function only based on changes in the stores involved in the last run.derived
: Re-run the function each time a dependent store changes.Asynchronous State:
+Asynchronous State:
computed
: Unable to manage asynchronous state.derived
: Can handle asynchronous state with the set
method.Skipping Value Emission:
+Skipping Value Emission:
computed
: Does not provide a mechanism to skip emitting values.derived
: Allows skipping the emission of values by choosing not to call the provided set
method.Setup and Teardown:
+Setup and Teardown:
computed
: Lacks explicit setup and teardown methods.derived
: Supports setup and teardown methods, allowing actions such as adding or removing DOM listeners.While computed
feels more intuitive in many use-cases, derived
excels in scenarios where computed
falls short, particularly in managing asynchronous state and providing more granular control over value emissions.
Carefully choosing between them based on specific requirements enhances the effectiveness of state management in your application.
-There are three ways for getting the value of a store:
-import {writable, get} from "@amadeus-it-group/tansu";
const count$ = writable(1);
const unsubscribe = count$.subscribe((count) => {
// Will be called with the updated value synchronously first, then each time count$ changes.
// `unsubscribe` must be called to prevent future calls.
console.log(count);
});
// A store is also a function that you can call to get the instant value.
console.log(count$());
// Equivalent to
console.log(get(count$));
-
+There are three ways for getting the value of a store:
+import {writable, get} from "@amadeus-it-group/tansu";
const count$ = writable(1);
const unsubscribe = count$.subscribe((count) => {
// Will be called with the updated value synchronously first, then each time count$ changes.
// `unsubscribe` must be called to prevent future calls.
console.log(count);
});
// A store is also a function that you can call to get the instant value.
console.log(count$());
// Equivalent to
console.log(get(count$));
+
+
-[!NOTE] Getting the instant value implies the subscription and unsubription on the store:
@@ -143,68 +164,77 @@When called inside a reactive context (i.e. inside a computed), getting the value serves to know and "listen" the dependent stores.
Contrary to other libraries like Angular with signals or Svelte with runes, where the callback of a subscription is executed asynchronously (usually referenced as an "effect"), we have maintained the constraint of synchronicity between the store changes and their subscriptions in Tansu.
While it is acceptable for these frameworks to defer these calls since their goals are well-known in advance (to optimize their final rendering), this is not the case for Tansu, where the goal is to be adaptable to any situation.
The problem with synchronous subscriptions is that it can create "glitches". Subscribers and computed store callbacks that are run too many times can create incorrect intermediate values.
-Svelte stores resolved the diamond dependency issue, but it does not match all the use-cases.
-Let's have a look at the following example:
-import {writable, derived} from '@amadeus-it-group/tansu';
const firstName = writable('Arsène');
const lastName = writable('Lupin');
const fullName = derived([firstName, lastName], ([a, b]) => `${a} ${b}`);
fullName.subscribe((name) => console.log(name)); // logs any change to fullName
firstName.set('Sherlock');
lastName.set('Holmes');
console.log('Process end');
-
+Svelte stores resolved the diamond dependency issue, but it does not match all the use-cases.
+Let's have a look at the following example:
+import {writable, derived} from '@amadeus-it-group/tansu';
const firstName = writable('Arsène');
const lastName = writable('Lupin');
const fullName = derived([firstName, lastName], ([a, b]) => `${a} ${b}`);
fullName.subscribe((name) => console.log(name)); // logs any change to fullName
firstName.set('Sherlock');
lastName.set('Holmes');
console.log('Process end');
+
+
output:
-Arsène Lupin
+Arsène Lupin
Sherlock Lupin
Sherlock Holmes
Process end
-
+
+
The fullName store successively went through different states, including an inconsistent one, as Sherlock Lupin
does not exist! Even if it can be seen as just an intermediate state, it is fundamental for a state management to only manage consistent data in order to prevent issues and optimize the code.
In Tansu, the batch
is available to defer synchronously the subscribers calls, and de facto the dependent derived
or computed
calculation to solve all kind of multiple dependencies issues.
The previous example is resolved this way:
-import {writable, derived, computed, batch} from '@amadeus-it-group/tansu';
const firstName = writable('Arsène');
const lastName = writable('Lupin');
const fullName = derived([firstName, lastName], ([a, b]) => `${a} ${b}`);
// note that the fullName store could alternatively be create with computed:
// const fullName = computed(() => `${firstName()} ${lastName()}`);
fullName.subscribe((name) => console.log(name)); // logs any change to fullName
batch(() => {
firstName.set('Sherlock');
lastName.set('Holmes');
});
console.log('Process end');
-
+import {writable, derived, computed, batch} from '@amadeus-it-group/tansu';
const firstName = writable('Arsène');
const lastName = writable('Lupin');
const fullName = derived([firstName, lastName], ([a, b]) => `${a} ${b}`);
// note that the fullName store could alternatively be create with computed:
// const fullName = computed(() => `${firstName()} ${lastName()}`);
fullName.subscribe((name) => console.log(name)); // logs any change to fullName
batch(() => {
firstName.set('Sherlock');
lastName.set('Holmes');
});
console.log('Process end');
+
+
output:
-Arsène Lupin
+Arsène Lupin
Sherlock Holmes
Process end
-
+
+
-[!NOTE]
- Retrieving the immediate value of a store (using any of the three methods mentioned earlier: calling
subscribe
with a subscriber that will be called with the value synchronously, usingget
or calling the store as a function) always provides the value based on the up-to-date values of all dependent stores (even if this requires re-computations of a computed or a derived inside the batch)- all calls to subscribers (excluding the first synchronous call during the subscribe process) are deferred until the end of the batch
-- if a subscriber has already been notified of a new value inside the batch (for example, when it is a new subscriber registered within the batch), it won't be notified again at the end of the batch if the value remains unchanged. Subscribers are invoked only when the store's value has changed since their last call.
+- if a subscriber has already been notified of a new value inside the batch (for example, when it is a new subscriber registered within the batch), it won't be notified again at the end of the batch if the value remains unchanged. Subscribers are invoked only when the store's value has changed since their last call.
batch
can be called insidebatch
. The subscriber calls are performed at the end of the first batch, synchronously.
asReadable
returns a new store that exposes only the essential elements needed for subscribing to the store. It also includes any extra methods passed as parameters.
This is useful and widely used to compose a custom store:
import {writable, asReadable} from "@amadeus-it-group/tansu";
function createCounter(initialValue: number) {
const store$ = writable(initialValue);
return asReadable(store$, {
increment: () => store$.update((value) => value + 1),
decrement: () => store$.update((value) => value - 1),
reset: () => store$.set(initialValue)
});
}
const counter$ = createCounter(0);
counter$.subscribe((value) => console.log('Value: ', value));
counter$.increment();
counter$.reset();
counter$.set(2); // Error, set does not exist
-
+import {writable, asReadable} from "@amadeus-it-group/tansu";
function createCounter(initialValue: number) {
const store$ = writable(initialValue);
return asReadable(store$, {
increment: () => store$.update((value) => value + 1),
decrement: () => store$.update((value) => value - 1),
reset: () => store$.set(initialValue)
});
}
const counter$ = createCounter(0);
counter$.subscribe((value) => console.log('Value: ', value));
counter$.increment();
counter$.reset();
counter$.set(2); // Error, set does not exist
+
+
output:
-Value: 0
+Value: 0
Value: 1
Value: 0
(Error thrown !)
-
-asWritable
-asWritable
is almost the same as an asReadable
, with the key difference being its implementation of the WritableSignal interface.
-It's useful when you want to connect your computed store to the original one, or implement a custom set
method. The set
method can be passed directly in the second parameter or within an object, similar to the usage in asReadable
.
+
+
+asWritable
is almost the same as an asReadable
, with the key difference being its implementation of the WritableSignal interface.
It's useful when you want to connect your computed store to the original one, or implement a custom set
method. The set
method can be passed directly in the second parameter or within an object, similar to the usage in asReadable
.
For example:
-import {writable, asWritable} from "@amadeus-it-group/tansu";
const number$ = writable(1);
const double$ = computed(() => number$() * 2);
const writableDouble$ = asWritable(double$, (doubleNumber) => {
number$.set(doubleNumber / 2);
});
/* equivalent to:
const writableDouble$ = asWritable(double$, {
set: (doubleNumber) => number$.set(doubleNumber / 2)
});
*/
writableDouble$.subscribe((value) => console.log('Value: ', value));
writableDouble$.set(2); // Nothing is triggered here, as number$ is already set with 1
writableDouble$.set(4);
-
+import {writable, asWritable} from "@amadeus-it-group/tansu";
const number$ = writable(1);
const double$ = computed(() => number$() * 2);
const writableDouble$ = asWritable(double$, (doubleNumber) => {
number$.set(doubleNumber / 2);
});
/* equivalent to:
const writableDouble$ = asWritable(double$, {
set: (doubleNumber) => number$.set(doubleNumber / 2)
});
*/
writableDouble$.subscribe((value) => console.log('Value: ', value));
writableDouble$.set(2); // Nothing is triggered here, as number$ is already set with 1
writableDouble$.set(4);
+
+
output:
-Value: 2
+Value: 2
Value: 4
-
-Integration in frameworks
Tansu works well with the Svelte framework
Tansu is designed to be and to remain fully compatible with Svelte.
-Tansu works well with the Angular ecosystem
Here is an example of an Angular component using a Tansu store:
-import { Component } from "@angular/core";
import { AsyncPipe } from '@angular/common';
import { Store, computed, get } from "@amadeus-it-group/tansu";
// A store is a class extending Store from Tansu
class CounterStore extends Store<number> {
constructor() {
super(0); // initialize store's value (state)
}
// implement state manipulation logic as regular methods
increment() {
// create new state based on the current state
this.update(value => value + 1);
}
reset() {
// replace the entire state with a new value
this.set(0);
}
}
@Component({
selector: "my-app",
template: `
<button (click)="counter$.increment()">+</button> <br />
<!-- store values can be displayed in a template with the standard async pipe -->
Counter: {{ counter$ | async }} <br />
Double counter: {{ doubleCounter$ | async }} <br />
`,
standalone: true,
imports: [AsyncPipe]
})
export class App {
// A store can be instantiated directly or registered in the DI container
counter$ = new CounterStore();
// One can easily create computed values by specifying a transformation function
doubleCounter$ = computed(() => 2 * get(this.counter$));
}
-
+
+
+Tansu is designed to be and to remain fully compatible with Svelte.
+Here is an example of an Angular component using a Tansu store:
+import { Component } from "@angular/core";
import { AsyncPipe } from '@angular/common';
import { Store, computed, get } from "@amadeus-it-group/tansu";
// A store is a class extending Store from Tansu
class CounterStore extends Store<number> {
constructor() {
super(0); // initialize store's value (state)
}
// implement state manipulation logic as regular methods
increment() {
// create new state based on the current state
this.update(value => value + 1);
}
reset() {
// replace the entire state with a new value
this.set(0);
}
}
@Component({
selector: "my-app",
template: `
<button (click)="counter$.increment()">+</button> <br />
<!-- store values can be displayed in a template with the standard async pipe -->
Counter: {{ counter$ | async }} <br />
Double counter: {{ doubleCounter$ | async }} <br />
`,
standalone: true,
imports: [AsyncPipe]
})
export class App {
// A store can be instantiated directly or registered in the DI container
counter$ = new CounterStore();
// One can easily create computed values by specifying a transformation function
doubleCounter$ = computed(() => 2 * get(this.counter$));
}
+
+
While being fairly minimal, this example demonstrates most of the Tansu APIs with Angular.
async
pipe out of the boxInteropObservable
interfaceInteropObservable
interface) can easily be used with Tansu (e.g. in Tansu computed
or derived
).Please check the DEVELOPER.md for documentation on building and testing the project on your local development machine.
-Please check the DEVELOPER.md for documentation on building and testing the project on your local development machine.
+Generated using TypeDoc
Optional
equalCustom function to compare two values, that should return true if they +
Optional
equalCustom function to compare two values, that should return true if they are equal.
It is called when setting a new value to avoid doing anything (such as notifying subscribers) if the value did not change.
-Custom function to compare two values, that should return true if they -are equal.
-It is called when setting a new value to avoid doing anything -(such as notifying subscribers) if the value did not change.
-First value to compare.
-Second value to compare.
+true if a and b are considered equal.
-The default logic (when this option is not present) is to return false +
The default logic (when this option is not present) is to return false
if a
is a function or an object, or if a
and b
are different
according to Object.is
.
equal takes precedence over notEqual if both are defined.
-First value to compare.
-Second value to compare.
-true if a and b are considered equal.
-Optional
notCustom function to compare two values, that should return true if they +
Optional
notCustom function to compare two values, that should return true if they are different.
It is called when setting a new value to avoid doing anything (such as notifying subscribers) if the value did not change.
-Custom function to compare two values, that should return true if they -are different.
-It is called when setting a new value to avoid doing anything -(such as notifying subscribers) if the value did not change.
-First value to compare.
-Second value to compare.
+true if a and b are considered different.
-The default logic (when this option is not present) is to return true
-if a
is a function or an object, or if a
and b
are different
-according to Object.is
.
StoreOptions.equal takes precedence over notEqual if both -are defined.
-Use StoreOptions.equal instead
-The default logic (when this option is not present) is to return true +
The default logic (when this option is not present) is to return true
if a
is a function or an object, or if a
and b
are different
according to Object.is
.
StoreOptions.equal takes precedence over notEqual if both are defined.
-Use StoreOptions.equal instead
-First value to compare.
-Second value to compare.
-true if a and b are considered different.
-Generated using TypeDoc
Use StoreOptions.equal instead
+An interface for interoperability between observable implementations. It only has to expose the [Symbol.observable]
method that is supposed to return a subscribable store.
Generated using TypeDoc
An interface for interoperability between observable implementations. It only has to expose the [Symbol.observable]
method that is supposed to return a subscribable store.
Generated using TypeDoc
This interface augments the base SubscribableStore interface by requiring the return value of the subscribe method to be both a function and an object with the unsubscribe
method.
This interface augments the base SubscribableStore interface by requiring the return value of the subscribe method to be both a function and an object with the unsubscribe
method.
For interoperability with rxjs, it also implements the [Symbol.observable]
method.
A method that makes it possible to register "interest" in store value changes over time. -It is called each and every time the store's value changes.
+A method that makes it possible to register "interest" in store value changes over time. +It is called each and every time the store's value changes.
A registered subscriber is notified synchronously with the latest store value.
-a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
The UnsubscribeFunction or UnsubscribeObject that can be used to unsubscribe (stop state change notifications).
-Generated using TypeDoc
This interface augments the base Readable interface by adding the ability to call the store as a function to get its value.
-A method that makes it possible to register "interest" in store value changes over time. -It is called each and every time the store's value changes.
+This interface augments the base Readable interface by adding the ability to call the store as a function to get its value.
+A method that makes it possible to register "interest" in store value changes over time. +It is called each and every time the store's value changes.
A registered subscriber is notified synchronously with the latest store value.
-a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
The UnsubscribeFunction or UnsubscribeObject that can be used to unsubscribe (stop state change notifications).
-Generated using TypeDoc
Optional
equalCustom function to compare two values, that should return true if they +
Optional
equalCustom function to compare two values, that should return true if they are equal.
It is called when setting a new value to avoid doing anything (such as notifying subscribers) if the value did not change.
-Custom function to compare two values, that should return true if they -are equal.
-It is called when setting a new value to avoid doing anything -(such as notifying subscribers) if the value did not change.
-First value to compare.
-Second value to compare.
+true if a and b are considered equal.
-The default logic (when this option is not present) is to return false +
The default logic (when this option is not present) is to return false
if a
is a function or an object, or if a
and b
are different
according to Object.is
.
equal takes precedence over notEqual if both are defined.
-First value to compare.
-Second value to compare.
-true if a and b are considered equal.
-Optional
notCustom function to compare two values, that should return true if they +
Optional
notCustom function to compare two values, that should return true if they are different.
It is called when setting a new value to avoid doing anything (such as notifying subscribers) if the value did not change.
-Custom function to compare two values, that should return true if they -are different.
-It is called when setting a new value to avoid doing anything -(such as notifying subscribers) if the value did not change.
-First value to compare.
-Second value to compare.
+true if a and b are considered different.
-The default logic (when this option is not present) is to return true
-if a
is a function or an object, or if a
and b
are different
-according to Object.is
.
StoreOptions.equal takes precedence over notEqual if both -are defined.
-Use StoreOptions.equal instead
-The default logic (when this option is not present) is to return true +
The default logic (when this option is not present) is to return true
if a
is a function or an object, or if a
and b
are different
according to Object.is
.
StoreOptions.equal takes precedence over notEqual if both are defined.
-Use StoreOptions.equal instead
-First value to compare.
-Second value to compare.
-true if a and b are considered different.
-Optional
onA function that is called when the number of subscribers changes from 0 to 1 +
Use StoreOptions.equal instead
+Optional
onA function that is called when the number of subscribers changes from 0 to 1 (but not called when the number of subscribers changes from 1 to 2, ...). If it returns a function, that function will be called when the number of subscribers changes from 1 to 0.
-Generated using TypeDoc
Represents a store accepting registrations (subscribers) and "pushing" notifications on each and every store value change.
-A method that makes it possible to register "interest" in store value changes over time. -It is called each and every time the store's value changes.
+Represents a store accepting registrations (subscribers) and "pushing" notifications on each and every store value change.
+A method that makes it possible to register "interest" in store value changes over time. +It is called each and every time the store's value changes.
A registered subscriber is notified synchronously with the latest store value.
-a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
The UnsubscribeFunction or UnsubscribeObject that can be used to unsubscribe (stop state change notifications).
-Generated using TypeDoc
Optional
completeUnused, only declared for compatibility with rxjs.
-Optional
errorUnused, only declared for compatibility with rxjs.
-A store will call this method every time the store's state is changing.
-A store will call this method when it knows that the value will be changed. +
Optional
completeUnused, only declared for compatibility with rxjs.
+Optional
errorUnused, only declared for compatibility with rxjs.
+A store will call this method every time the store's state is changing.
+A store will call this method if pause was called previously -and the value finally did not need to change.
-Generated using TypeDoc
Optional
equalCustom function to compare two values, that should return true if they +
Optional
equalCustom function to compare two values, that should return true if they are equal.
It is called when setting a new value to avoid doing anything (such as notifying subscribers) if the value did not change.
-Custom function to compare two values, that should return true if they -are equal.
-It is called when setting a new value to avoid doing anything -(such as notifying subscribers) if the value did not change.
-First value to compare.
-Second value to compare.
+true if a and b are considered equal.
-The default logic (when this option is not present) is to return false +
The default logic (when this option is not present) is to return false
if a
is a function or an object, or if a
and b
are different
according to Object.is
.
equal takes precedence over notEqual if both are defined.
-First value to compare.
-Second value to compare.
-true if a and b are considered equal.
-Optional
notCustom function to compare two values, that should return true if they +
Optional
notCustom function to compare two values, that should return true if they are different.
It is called when setting a new value to avoid doing anything (such as notifying subscribers) if the value did not change.
-Custom function to compare two values, that should return true if they -are different.
-It is called when setting a new value to avoid doing anything -(such as notifying subscribers) if the value did not change.
-First value to compare.
-Second value to compare.
+true if a and b are considered different.
-The default logic (when this option is not present) is to return true
-if a
is a function or an object, or if a
and b
are different
-according to Object.is
.
StoreOptions.equal takes precedence over notEqual if both -are defined.
-Use StoreOptions.equal instead
-The default logic (when this option is not present) is to return true +
The default logic (when this option is not present) is to return true
if a
is a function or an object, or if a
and b
are different
according to Object.is
.
StoreOptions.equal takes precedence over notEqual if both are defined.
-Use StoreOptions.equal instead
-First value to compare.
-Second value to compare.
-true if a and b are considered different.
-Generated using TypeDoc
Use StoreOptions.equal instead
+An object with the unsubscribe
method.
+
An object with the unsubscribe
method.
Subscribable stores might choose to return such object instead of directly returning UnsubscribeFunction from a subscription call.
A method that acts as the UnsubscribeFunction.
-Generated using TypeDoc
A method that acts as the UnsubscribeFunction.
+Builds on top of Readable and represents a store that can be manipulated from "outside": anyone with a reference to writable store can either update or completely replace state of a given store.
-// reset counter's store value to 0 by using the {@link Writable.set} method
counterStore.set(0);
// increment counter's store value by using the {@link Writable.update} method
counterStore.update(currentValue => currentValue + 1);
-
-Replaces store's state with the provided value.
-value to be used as the new state of a store.
-A method that makes it possible to register "interest" in store value changes over time. -It is called each and every time the store's value changes.
+Builds on top of Readable and represents a store that can be manipulated from "outside": anyone with a reference to writable store can either update or completely replace state of a given store.
+Replaces store's state with the provided value.
+value to be used as the new state of a store.
+A method that makes it possible to register "interest" in store value changes over time. +It is called each and every time the store's value changes.
A registered subscriber is notified synchronously with the latest store value.
-a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
The UnsubscribeFunction or UnsubscribeObject that can be used to unsubscribe (stop state change notifications).
-Generated using TypeDoc
Represents a store that implements both ReadableSignal and Writable. +
Represents a store that implements both ReadableSignal and Writable. This is the type of objects returned by writable.
-Replaces store's state with the provided value.
-value to be used as the new state of a store.
-A method that makes it possible to register "interest" in store value changes over time. -It is called each and every time the store's value changes.
+Replaces store's state with the provided value.
+value to be used as the new state of a store.
+A method that makes it possible to register "interest" in store value changes over time. +It is called each and every time the store's value changes.
A registered subscriber is notified synchronously with the latest store value.
-a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
a subscriber in a form of a SubscriberFunction or a SubscriberObject. Returns a Unsubscriber (function or object with the unsubscribe
method) that can be used to unregister and stop receiving notifications of store value changes.
The UnsubscribeFunction or UnsubscribeObject that can be used to unsubscribe (stop state change notifications).
-Generated using TypeDoc
tansu is a lightweight, push-based state management library. +
tansu is a lightweight, push-based state management library. It borrows the ideas and APIs originally designed and implemented by Svelte stores.
-Generated using TypeDoc
Generated using TypeDoc
Type of a function that is called when the number of subscribers changes from 0 to 1 +
Type of a function that is called when the number of subscribers changes from 0 to 1 (but not called when the number of subscribers changes from 1 to 2, ...).
If it returns a function, that function will be called when the number of subscribers changes from 1 to 0.
-Generated using TypeDoc
Valid types that can be considered as a store.
-Generated using TypeDoc
Valid types that can be considered as a store.
+Either a single StoreInput or a read-only array of at least one StoreInput.
-Generated using TypeDoc
Either a single StoreInput or a read-only array of at least one StoreInput.
+Extracts the types of the values of the stores from a type extending StoresInput.
-If the type given as a parameter is a single StoreInput, the type of the value +
Extracts the types of the values of the stores from a type extending StoresInput.
+If the type given as a parameter is a single StoreInput, the type of the value of that StoreInput is returned.
If the type given as a parameter is one of an array of StoreInput, the returned type is the type of an array containing the value of each store in the same order.
-Generated using TypeDoc
Expresses interest in store value changes over time. It can be either:
+Expresses interest in store value changes over time. It can be either:
Generated using TypeDoc
A callback invoked when a store value changes. It is called with the latest value of a given store.
-Generated using TypeDoc
A callback invoked when a store value changes. It is called with the latest value of a given store.
+Generated using TypeDoc
A function to unsubscribe from value change notifications.
-Generated using TypeDoc
A function to unsubscribe from value change notifications.
+Generated using TypeDoc
Generated using TypeDoc
Const
Symbol used in InteropObservable allowing any object to expose an observable.
-Generated using TypeDoc
Const
Symbol used in InteropObservable allowing any object to expose an observable.
+
Base class that can be extended to easily create a custom Readable store.
-Example
-