diff --git a/index.d.ts b/index.d.ts index c5e5b90d76..cda2d13df6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,3 +1,5 @@ +/// + /** * An *action* is a plain object that represents an intention to change the * state. Actions are the only way to get data into the store. Any data, @@ -128,6 +130,32 @@ export interface Unsubscribe { (): void } +/** + * A minimal observable of state changes. + * For more information, see the observable proposal: + * https://github.com/tc39/proposal-observable + */ +export type Observable = { + /** + * The minimal observable subscription method. + * @param {Object} observer Any object that can be used as an observer. + * The observer object should have a `next` method. + * @returns {subscription} An object with an `unsubscribe` method that can + * be used to unsubscribe the observable from the store, and prevent further + * emission of values from the observable. + */ + subscribe: (observer: Observer) => { unsubscribe: Unsubscribe } + [Symbol.observable](): Observable +} + +/** + * An Observer is used to receive data from an Observable, and is supplied as + * an argument to subscribe. + */ +export type Observer = { + next?(value: T): void +} + /** * A store is an object that holds the application's state tree. * There should only be a single store in a Redux app, as the composition @@ -208,6 +236,14 @@ export interface Store { * @param nextReducer The reducer for the store to use instead. */ replaceReducer(nextReducer: Reducer): void + + /** + * Interoperability point for observable/reactive libraries. + * @returns {observable} A minimal observable of state changes. + * For more information, see the observable proposal: + * https://github.com/tc39/proposal-observable + */ + [Symbol.observable](): Observable } export type DeepPartial = { [K in keyof T]?: DeepPartial } diff --git a/test/typescript/store.ts b/test/typescript/store.ts index 954d77b196..fb1974ab41 100644 --- a/test/typescript/store.ts +++ b/test/typescript/store.ts @@ -6,8 +6,10 @@ import { StoreEnhancer, StoreCreator, StoreEnhancerStoreCreator, - Unsubscribe + Unsubscribe, + Observer } from 'redux' +import 'symbol-observable' type State = { a: 'a' @@ -101,3 +103,15 @@ unsubscribe() const newReducer: Reducer = reducer store.replaceReducer(newReducer) + +/* observable */ + +let observable = store[Symbol.observable]() +observable = observable[Symbol.observable]() +const observer: Observer = { + next(state: State) { + console.log('current state:', state) + } +} +const unsubscribeFromObservable = observable.subscribe(observer).unsubscribe +unsubscribeFromObservable()