react-rx 3.0.0-6 → 3.0.0-crx-749.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {Observable} from 'rxjs'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
/** @internal */
|
|
4
|
+
export declare type UnboxObservable<T> = T extends Observable<infer U> ? U : never
|
|
3
5
|
|
|
4
6
|
/** @public */
|
|
5
7
|
export declare function useObservable<ObservableType extends Observable<any>>(
|
|
6
8
|
observable: ObservableType,
|
|
7
|
-
initialValue?:
|
|
8
|
-
):
|
|
9
|
+
initialValue?: UnboxObservable<ObservableType> | (() => UnboxObservable<ObservableType>),
|
|
10
|
+
): UnboxObservable<ObservableType>
|
|
9
11
|
|
|
10
12
|
/** @public */
|
|
11
13
|
export declare function useObservableEvent<T, U>(
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {Observable} from 'rxjs'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
/** @internal */
|
|
4
|
+
export declare type UnboxObservable<T> = T extends Observable<infer U> ? U : never
|
|
3
5
|
|
|
4
6
|
/** @public */
|
|
5
7
|
export declare function useObservable<ObservableType extends Observable<any>>(
|
|
6
8
|
observable: ObservableType,
|
|
7
|
-
initialValue?:
|
|
8
|
-
):
|
|
9
|
+
initialValue?: UnboxObservable<ObservableType> | (() => UnboxObservable<ObservableType>),
|
|
10
|
+
): UnboxObservable<ObservableType>
|
|
9
11
|
|
|
10
12
|
/** @public */
|
|
11
13
|
export declare function useObservableEvent<T, U>(
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/useObservable.ts","../src/useObservableEvent.ts"],"sourcesContent":["import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'\nimport type {Observable,
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/useObservable.ts","../src/useObservableEvent.ts"],"sourcesContent":["import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'\nimport type {Observable, Subscription} from 'rxjs'\nimport {shareReplay, tap} from 'rxjs/operators'\n\nfunction getValue<T>(value: T): T extends () => infer U ? U : T {\n return typeof value === 'function' ? value() : value\n}\ninterface CacheRecord<T> {\n subscription: Subscription\n observable: Observable<T>\n snapshot: T\n}\n\nconst cache = new WeakMap<Observable<any>, CacheRecord<any>>()\n\n/** @public */\nexport function useObservable<ObservableType extends Observable<any>>(\n observable: ObservableType,\n initialValue?: UnboxObservable<ObservableType> | (() => UnboxObservable<ObservableType>),\n): UnboxObservable<ObservableType> {\n /**\n * Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.\n * But we also don't want the initialValue to be stale if the observable changes.\n */\n const initialValueRef = useRef(getValue(initialValue) as UnboxObservable<ObservableType>)\n\n /**\n * Ensures that the initialValue is always up-to-date in case the observable changes.\n */\n useEffect(() => {\n initialValueRef.current = getValue(initialValue) as UnboxObservable<ObservableType>\n }, [initialValue])\n\n const store = useMemo(() => {\n if (!cache.has(observable)) {\n const entry: Partial<CacheRecord<UnboxObservable<ObservableType>>> = {\n snapshot: initialValueRef.current,\n }\n entry.observable = observable.pipe(\n shareReplay({refCount: true, bufferSize: 1}),\n tap((value) => (entry.snapshot = value)),\n )\n\n // Eagerly subscribe to sync set `entry.currentValue` to what the observable returns, and keep the observable alive until the component unmounts.\n entry.subscription = entry.observable.subscribe()\n\n cache.set(observable, entry as CacheRecord<UnboxObservable<ObservableType>>)\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const instance = cache.get(observable)!\n if (instance.subscription.closed) {\n instance.subscription = instance.observable.subscribe()\n }\n\n return {\n subscribe: (onStoreChange: () => void) => {\n const subscription = instance.observable.subscribe(onStoreChange)\n instance.subscription.unsubscribe()\n return () => subscription.unsubscribe()\n },\n getSnapshot: () => instance.snapshot,\n }\n }, [observable])\n\n return useSyncExternalStore<UnboxObservable<ObservableType>>(store.subscribe, store.getSnapshot)\n}\n\n/** @internal */\nexport type UnboxObservable<T> = T extends Observable<infer U> ? U : never\n","import {observableCallback} from 'observable-callback'\nimport {useCallback, useEffect, useInsertionEffect, useRef, useState} from 'react'\nimport {type Observable} from 'rxjs'\n\n/** @public */\nexport function useObservableEvent<T, U>(\n fn: (arg: Observable<T>) => Observable<U>,\n): (arg: T) => void {\n const [[calls$, call]] = useState(() => observableCallback<T>())\n\n const callback = useEffectEvent(fn)\n\n useEffect(() => {\n const subscription = calls$.pipe(callback).subscribe()\n return () => subscription.unsubscribe()\n }, [callback, calls$])\n\n return call\n}\n\n/**\n * This is a ponyfill of the upcoming `useEffectEvent` hook that'll arrive in React 19\n */\nfunction useEffectEvent<\n const T extends (\n ...args: // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any[]\n ) => void,\n>(fn: T): T {\n const ref = useRef<T | null>(null)\n useInsertionEffect(() => {\n ref.current = fn\n }, [fn])\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return useCallback((...args: any[]) => {\n const f = ref.current!\n return f(...args)\n }, []) as T\n}\n"],"names":["useRef","useEffect","useMemo","shareReplay","tap","useSyncExternalStore","useState","observableCallback","useInsertionEffect","useCallback"],"mappings":";;;AAIA,SAAS,SAAY,OAA2C;AAC9D,SAAO,OAAO,SAAU,aAAa,MAAA,IAAU;AACjD;AAOA,MAAM,4BAAY;AAGF,SAAA,cACd,YACA,cACiC;AAKjC,QAAM,kBAAkBA,MAAA,OAAO,SAAS,YAAY,CAAoC;AAKxFC,QAAAA,UAAU,MAAM;AACE,oBAAA,UAAU,SAAS,YAAY;AAAA,EAAA,GAC9C,CAAC,YAAY,CAAC;AAEX,QAAA,QAAQC,MAAAA,QAAQ,MAAM;AAC1B,QAAI,CAAC,MAAM,IAAI,UAAU,GAAG;AAC1B,YAAM,QAA+D;AAAA,QACnE,UAAU,gBAAgB;AAAA,MAAA;AAE5B,YAAM,aAAa,WAAW;AAAA,QAC5BC,sBAAY,EAAC,UAAU,IAAM,YAAY,GAAE;AAAA,QAC3CC,UAAAA,IAAI,CAAC,UAAW,MAAM,WAAW,KAAM;AAAA,MACzC,GAGA,MAAM,eAAe,MAAM,WAAW,aAEtC,MAAM,IAAI,YAAY,KAAqD;AAAA,IAC7E;AAEM,UAAA,WAAW,MAAM,IAAI,UAAU;AACjC,WAAA,SAAS,aAAa,WACxB,SAAS,eAAe,SAAS,WAAW,cAGvC;AAAA,MACL,WAAW,CAAC,kBAA8B;AACxC,cAAM,eAAe,SAAS,WAAW,UAAU,aAAa;AAChE,eAAA,SAAS,aAAa,YACf,GAAA,MAAM,aAAa;MAC5B;AAAA,MACA,aAAa,MAAM,SAAS;AAAA,IAAA;AAAA,EAC9B,GACC,CAAC,UAAU,CAAC;AAEf,SAAOC,MAAsD,qBAAA,MAAM,WAAW,MAAM,WAAW;AACjG;AC5DO,SAAS,mBACd,IACkB;AAClB,QAAM,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAIC,MAAS,SAAA,MAAMC,mBAAsB,mBAAA,CAAC,GAEzD,WAAW,eAAe,EAAE;AAElC,SAAAN,MAAA,UAAU,MAAM;AACd,UAAM,eAAe,OAAO,KAAK,QAAQ,EAAE,UAAU;AAC9C,WAAA,MAAM,aAAa;EACzB,GAAA,CAAC,UAAU,MAAM,CAAC,GAEd;AACT;AAKA,SAAS,eAKP,IAAU;AACJ,QAAA,MAAMD,aAAiB,IAAI;AACjC,SAAAQ,MAAA,mBAAmB,MAAM;AACvB,QAAI,UAAU;AAAA,KACb,CAAC,EAAE,CAAC,GAEAC,MAAAA,YAAY,IAAI,SAAgB;AACrC,UAAM,IAAI,IAAI;AACP,WAAA,EAAE,GAAG,IAAI;AAAA,EAClB,GAAG,CAAE,CAAA;AACP;;;"}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../src/useObservable.ts","../src/useObservableEvent.ts"],"sourcesContent":["import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'\nimport type {Observable,
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/useObservable.ts","../src/useObservableEvent.ts"],"sourcesContent":["import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'\nimport type {Observable, Subscription} from 'rxjs'\nimport {shareReplay, tap} from 'rxjs/operators'\n\nfunction getValue<T>(value: T): T extends () => infer U ? U : T {\n return typeof value === 'function' ? value() : value\n}\ninterface CacheRecord<T> {\n subscription: Subscription\n observable: Observable<T>\n snapshot: T\n}\n\nconst cache = new WeakMap<Observable<any>, CacheRecord<any>>()\n\n/** @public */\nexport function useObservable<ObservableType extends Observable<any>>(\n observable: ObservableType,\n initialValue?: UnboxObservable<ObservableType> | (() => UnboxObservable<ObservableType>),\n): UnboxObservable<ObservableType> {\n /**\n * Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.\n * But we also don't want the initialValue to be stale if the observable changes.\n */\n const initialValueRef = useRef(getValue(initialValue) as UnboxObservable<ObservableType>)\n\n /**\n * Ensures that the initialValue is always up-to-date in case the observable changes.\n */\n useEffect(() => {\n initialValueRef.current = getValue(initialValue) as UnboxObservable<ObservableType>\n }, [initialValue])\n\n const store = useMemo(() => {\n if (!cache.has(observable)) {\n const entry: Partial<CacheRecord<UnboxObservable<ObservableType>>> = {\n snapshot: initialValueRef.current,\n }\n entry.observable = observable.pipe(\n shareReplay({refCount: true, bufferSize: 1}),\n tap((value) => (entry.snapshot = value)),\n )\n\n // Eagerly subscribe to sync set `entry.currentValue` to what the observable returns, and keep the observable alive until the component unmounts.\n entry.subscription = entry.observable.subscribe()\n\n cache.set(observable, entry as CacheRecord<UnboxObservable<ObservableType>>)\n }\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const instance = cache.get(observable)!\n if (instance.subscription.closed) {\n instance.subscription = instance.observable.subscribe()\n }\n\n return {\n subscribe: (onStoreChange: () => void) => {\n const subscription = instance.observable.subscribe(onStoreChange)\n instance.subscription.unsubscribe()\n return () => subscription.unsubscribe()\n },\n getSnapshot: () => instance.snapshot,\n }\n }, [observable])\n\n return useSyncExternalStore<UnboxObservable<ObservableType>>(store.subscribe, store.getSnapshot)\n}\n\n/** @internal */\nexport type UnboxObservable<T> = T extends Observable<infer U> ? U : never\n","import {observableCallback} from 'observable-callback'\nimport {useCallback, useEffect, useInsertionEffect, useRef, useState} from 'react'\nimport {type Observable} from 'rxjs'\n\n/** @public */\nexport function useObservableEvent<T, U>(\n fn: (arg: Observable<T>) => Observable<U>,\n): (arg: T) => void {\n const [[calls$, call]] = useState(() => observableCallback<T>())\n\n const callback = useEffectEvent(fn)\n\n useEffect(() => {\n const subscription = calls$.pipe(callback).subscribe()\n return () => subscription.unsubscribe()\n }, [callback, calls$])\n\n return call\n}\n\n/**\n * This is a ponyfill of the upcoming `useEffectEvent` hook that'll arrive in React 19\n */\nfunction useEffectEvent<\n const T extends (\n ...args: // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any[]\n ) => void,\n>(fn: T): T {\n const ref = useRef<T | null>(null)\n useInsertionEffect(() => {\n ref.current = fn\n }, [fn])\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return useCallback((...args: any[]) => {\n const f = ref.current!\n return f(...args)\n }, []) as T\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,SAAY,OAA2C;AAC9D,SAAO,OAAO,SAAU,aAAa,MAAA,IAAU;AACjD;AAOA,MAAM,4BAAY;AAGF,SAAA,cACd,YACA,cACiC;AAKjC,QAAM,kBAAkB,OAAO,SAAS,YAAY,CAAoC;AAKxF,YAAU,MAAM;AACE,oBAAA,UAAU,SAAS,YAAY;AAAA,EAAA,GAC9C,CAAC,YAAY,CAAC;AAEX,QAAA,QAAQ,QAAQ,MAAM;AAC1B,QAAI,CAAC,MAAM,IAAI,UAAU,GAAG;AAC1B,YAAM,QAA+D;AAAA,QACnE,UAAU,gBAAgB;AAAA,MAAA;AAE5B,YAAM,aAAa,WAAW;AAAA,QAC5B,YAAY,EAAC,UAAU,IAAM,YAAY,GAAE;AAAA,QAC3C,IAAI,CAAC,UAAW,MAAM,WAAW,KAAM;AAAA,MACzC,GAGA,MAAM,eAAe,MAAM,WAAW,aAEtC,MAAM,IAAI,YAAY,KAAqD;AAAA,IAC7E;AAEM,UAAA,WAAW,MAAM,IAAI,UAAU;AACjC,WAAA,SAAS,aAAa,WACxB,SAAS,eAAe,SAAS,WAAW,cAGvC;AAAA,MACL,WAAW,CAAC,kBAA8B;AACxC,cAAM,eAAe,SAAS,WAAW,UAAU,aAAa;AAChE,eAAA,SAAS,aAAa,YACf,GAAA,MAAM,aAAa;MAC5B;AAAA,MACA,aAAa,MAAM,SAAS;AAAA,IAAA;AAAA,EAC9B,GACC,CAAC,UAAU,CAAC;AAEf,SAAO,qBAAsD,MAAM,WAAW,MAAM,WAAW;AACjG;AC5DO,SAAS,mBACd,IACkB;AAClB,QAAM,CAAC,CAAC,QAAQ,IAAI,CAAC,IAAI,SAAS,MAAM,mBAAsB,CAAC,GAEzD,WAAW,eAAe,EAAE;AAElC,SAAA,UAAU,MAAM;AACd,UAAM,eAAe,OAAO,KAAK,QAAQ,EAAE,UAAU;AAC9C,WAAA,MAAM,aAAa;EACzB,GAAA,CAAC,UAAU,MAAM,CAAC,GAEd;AACT;AAKA,SAAS,eAKP,IAAU;AACJ,QAAA,MAAM,OAAiB,IAAI;AACjC,SAAA,mBAAmB,MAAM;AACvB,QAAI,UAAU;AAAA,KACb,CAAC,EAAE,CAAC,GAEA,YAAY,IAAI,SAAgB;AACrC,UAAM,IAAI,IAAI;AACP,WAAA,EAAE,GAAG,IAAI;AAAA,EAClB,GAAG,CAAE,CAAA;AACP;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-rx",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-crx-749.1",
|
|
4
4
|
"description": "React + RxJS = <3",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"action",
|
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
"pipe",
|
|
16
16
|
"react",
|
|
17
17
|
"react18",
|
|
18
|
-
"react19",
|
|
19
18
|
"reactive",
|
|
20
19
|
"realtime",
|
|
21
20
|
"rx",
|
|
@@ -29,6 +28,7 @@
|
|
|
29
28
|
"sync",
|
|
30
29
|
"typesafe",
|
|
31
30
|
"typescript",
|
|
31
|
+
"use-sync-external-store",
|
|
32
32
|
"use"
|
|
33
33
|
],
|
|
34
34
|
"homepage": "https://react-rx.dev",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"dev": "cd website && npm run dev",
|
|
72
72
|
"prepublishOnly": "npm run build",
|
|
73
73
|
"watch": "npm run build -- --watch",
|
|
74
|
-
"test": "
|
|
74
|
+
"test": "jest",
|
|
75
75
|
"lint": "eslint --cache ."
|
|
76
76
|
},
|
|
77
77
|
"browserslist": "extends @sanity/browserslist-config",
|
|
@@ -80,11 +80,12 @@
|
|
|
80
80
|
"observable-callback": "^1.0.3"
|
|
81
81
|
},
|
|
82
82
|
"devDependencies": {
|
|
83
|
-
"@sanity/pkg-utils": "^6.9.
|
|
83
|
+
"@sanity/pkg-utils": "^6.9.2",
|
|
84
84
|
"@sanity/prettier-config": "^1.0.2",
|
|
85
85
|
"@sanity/semantic-release-preset": "^4.1.8",
|
|
86
86
|
"@testing-library/dom": "^10.1.0",
|
|
87
87
|
"@testing-library/react": "^16.0.0",
|
|
88
|
+
"@types/jest": "^29.5.3",
|
|
88
89
|
"@types/node": "^18.17.5",
|
|
89
90
|
"@types/react": "^18.3.3",
|
|
90
91
|
"@types/react-dom": "^18.3.0",
|
|
@@ -97,6 +98,9 @@
|
|
|
97
98
|
"eslint-plugin-react-compiler": "0.0.0-experimental-51a85ea-20240601",
|
|
98
99
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
99
100
|
"eslint-plugin-simple-import-sort": "^12.1.0",
|
|
101
|
+
"jest": "^29.6.2",
|
|
102
|
+
"jest-environment-jsdom": "^29.6.2",
|
|
103
|
+
"jsdom": "^20.0.3",
|
|
100
104
|
"npm-run-all": "^4.1.5",
|
|
101
105
|
"prettier": "^3.3.1",
|
|
102
106
|
"react": "^18.3.1",
|
|
@@ -104,8 +108,8 @@
|
|
|
104
108
|
"react-test-renderer": "^18.3.1",
|
|
105
109
|
"rxjs": "^7.8.1",
|
|
106
110
|
"semantic-release": "^24.0.0",
|
|
107
|
-
"
|
|
108
|
-
"
|
|
111
|
+
"ts-jest": "^29.1.1",
|
|
112
|
+
"typescript": "5.4.5"
|
|
109
113
|
},
|
|
110
114
|
"peerDependencies": {
|
|
111
115
|
"react": "^18.3 || >=19.0.0-rc",
|
|
@@ -2,7 +2,6 @@ import {act, render, renderHook} from '@testing-library/react'
|
|
|
2
2
|
import {createElement, Fragment} from 'react'
|
|
3
3
|
import {asyncScheduler, Observable, of, scheduled, Subject, timer} from 'rxjs'
|
|
4
4
|
import {mapTo} from 'rxjs/operators'
|
|
5
|
-
import {expect, test} from 'vitest'
|
|
6
5
|
|
|
7
6
|
import {useObservable} from '../useObservable'
|
|
8
7
|
|
package/src/useObservable.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {useEffect, useMemo, useRef, useSyncExternalStore} from 'react'
|
|
2
|
-
import type {Observable,
|
|
2
|
+
import type {Observable, Subscription} from 'rxjs'
|
|
3
3
|
import {shareReplay, tap} from 'rxjs/operators'
|
|
4
4
|
|
|
5
5
|
function getValue<T>(value: T): T extends () => infer U ? U : T {
|
|
@@ -16,24 +16,24 @@ const cache = new WeakMap<Observable<any>, CacheRecord<any>>()
|
|
|
16
16
|
/** @public */
|
|
17
17
|
export function useObservable<ObservableType extends Observable<any>>(
|
|
18
18
|
observable: ObservableType,
|
|
19
|
-
initialValue?:
|
|
20
|
-
):
|
|
19
|
+
initialValue?: UnboxObservable<ObservableType> | (() => UnboxObservable<ObservableType>),
|
|
20
|
+
): UnboxObservable<ObservableType> {
|
|
21
21
|
/**
|
|
22
22
|
* Store the initialValue in a ref, as we don't want a changed `initialValue` to trigger a re-subscription.
|
|
23
23
|
* But we also don't want the initialValue to be stale if the observable changes.
|
|
24
24
|
*/
|
|
25
|
-
const initialValueRef = useRef(getValue(initialValue) as
|
|
25
|
+
const initialValueRef = useRef(getValue(initialValue) as UnboxObservable<ObservableType>)
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
28
|
* Ensures that the initialValue is always up-to-date in case the observable changes.
|
|
29
29
|
*/
|
|
30
30
|
useEffect(() => {
|
|
31
|
-
initialValueRef.current = getValue(initialValue) as
|
|
31
|
+
initialValueRef.current = getValue(initialValue) as UnboxObservable<ObservableType>
|
|
32
32
|
}, [initialValue])
|
|
33
33
|
|
|
34
34
|
const store = useMemo(() => {
|
|
35
35
|
if (!cache.has(observable)) {
|
|
36
|
-
const entry: Partial<CacheRecord<
|
|
36
|
+
const entry: Partial<CacheRecord<UnboxObservable<ObservableType>>> = {
|
|
37
37
|
snapshot: initialValueRef.current,
|
|
38
38
|
}
|
|
39
39
|
entry.observable = observable.pipe(
|
|
@@ -44,7 +44,7 @@ export function useObservable<ObservableType extends Observable<any>>(
|
|
|
44
44
|
// Eagerly subscribe to sync set `entry.currentValue` to what the observable returns, and keep the observable alive until the component unmounts.
|
|
45
45
|
entry.subscription = entry.observable.subscribe()
|
|
46
46
|
|
|
47
|
-
cache.set(observable, entry as CacheRecord<
|
|
47
|
+
cache.set(observable, entry as CacheRecord<UnboxObservable<ObservableType>>)
|
|
48
48
|
}
|
|
49
49
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
50
50
|
const instance = cache.get(observable)!
|
|
@@ -62,5 +62,8 @@ export function useObservable<ObservableType extends Observable<any>>(
|
|
|
62
62
|
}
|
|
63
63
|
}, [observable])
|
|
64
64
|
|
|
65
|
-
return useSyncExternalStore<
|
|
65
|
+
return useSyncExternalStore<UnboxObservable<ObservableType>>(store.subscribe, store.getSnapshot)
|
|
66
66
|
}
|
|
67
|
+
|
|
68
|
+
/** @internal */
|
|
69
|
+
export type UnboxObservable<T> = T extends Observable<infer U> ? U : never
|