types: watch API type overload

This commit is contained in:
Evan You 2019-08-18 22:49:08 -04:00
parent 6a22ad2fb2
commit 42559dc5fe

View File

@ -17,19 +17,66 @@ export interface WatchOptions {
onTrigger?: ReactiveEffectOptions['onTrigger'] onTrigger?: ReactiveEffectOptions['onTrigger']
} }
type WatcherSource<T> = Ref<T> | (() => T) type StopHandle = () => void
type WatcherSource<T = any> = Ref<T> | (() => T)
type MapSources<T> = {
[K in keyof T]: T[K] extends WatcherSource<infer V> ? V : never
}
type CleanupRegistrator = (invalidate: () => void) => void
type SimpleEffect = (onCleanup: CleanupRegistrator) => void
const invoke = (fn: Function) => fn() const invoke = (fn: Function) => fn()
export function watch(effect: SimpleEffect, options?: WatchOptions): StopHandle
export function watch<T>( export function watch<T>(
source: WatcherSource<T> | WatcherSource<T>[], source: WatcherSource<T>,
cb?: <V extends T>( cb: (newValue: T, oldValue: T, onCleanup: CleanupRegistrator) => any,
newValue: V, options?: WatchOptions
oldValue: V, ): StopHandle
onInvalidate: (fn: () => void) => void
) => any | void, export function watch<T extends WatcherSource<unknown>[]>(
{ lazy, flush, deep, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ sources: T,
): () => void { cb: (
newValues: MapSources<T>,
oldValues: MapSources<T>,
onCleanup: CleanupRegistrator
) => any,
options?: WatchOptions
): StopHandle
// implementation
export function watch(
effectOrSource:
| WatcherSource<unknown>
| WatcherSource<unknown>[]
| SimpleEffect,
effectOrOptions?:
| ((value: any, oldValue: any, onCleanup: CleanupRegistrator) => any)
| WatchOptions,
options?: WatchOptions
): StopHandle {
if (typeof effectOrOptions === 'function') {
// effect callback as 2nd argument - this is a source watcher
return doWatch(effectOrSource, effectOrOptions, options)
} else {
// 2nd argument is either missing or an options object
// - this is a simple effect watcher
return doWatch(effectOrSource, null, effectOrOptions)
}
}
function doWatch(
source: WatcherSource | WatcherSource[] | SimpleEffect,
cb:
| ((newValue: any, oldValue: any, onCleanup: CleanupRegistrator) => any)
| null,
{ lazy, deep, flush, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ
): StopHandle {
const scheduler = const scheduler =
flush === 'sync' ? invoke : flush === 'pre' ? queueJob : queuePostFlushCb flush === 'sync' ? invoke : flush === 'pre' ? queueJob : queuePostFlushCb
@ -37,11 +84,11 @@ export function watch<T>(
? () => source.map(s => (isRef(s) ? s.value : s())) ? () => source.map(s => (isRef(s) ? s.value : s()))
: isRef(source) : isRef(source)
? () => source.value ? () => source.value
: source : () => source(registerCleanup)
const getter = deep ? () => traverse(baseGetter()) : baseGetter const getter = deep ? () => traverse(baseGetter()) : baseGetter
let cleanup: any let cleanup: any
const registerCleanup = (fn: () => void) => { const registerCleanup: CleanupRegistrator = (fn: () => void) => {
// TODO wrap the cleanup fn for error handling // TODO wrap the cleanup fn for error handling
cleanup = runner.onStop = fn cleanup = runner.onStop = fn
} }