]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
types: watch API type overload
authorEvan You <yyx990803@gmail.com>
Mon, 19 Aug 2019 02:49:08 +0000 (22:49 -0400)
committerEvan You <yyx990803@gmail.com>
Mon, 19 Aug 2019 02:49:08 +0000 (22:49 -0400)
packages/runtime-core/src/apiWatch.ts

index a92596f475c2994fffc614e5f9fb6aed21a4fee8..0f9e51866e971339f278ef7662380854992383de 100644 (file)
@@ -17,19 +17,66 @@ export interface WatchOptions {
   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()
 
+export function watch(effect: SimpleEffect, options?: WatchOptions): StopHandle
+
 export function watch<T>(
-  source: WatcherSource<T> | WatcherSource<T>[],
-  cb?: <V extends T>(
-    newValue: V,
-    oldValue: V,
-    onInvalidate: (fn: () => void) => void
-  ) => any | void,
-  { lazy, flush, deep, onTrack, onTrigger }: WatchOptions = EMPTY_OBJ
-): () => void {
+  source: WatcherSource<T>,
+  cb: (newValue: T, oldValue: T, onCleanup: CleanupRegistrator) => any,
+  options?: WatchOptions
+): StopHandle
+
+export function watch<T extends WatcherSource<unknown>[]>(
+  sources: T,
+  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 =
     flush === 'sync' ? invoke : flush === 'pre' ? queueJob : queuePostFlushCb
 
@@ -37,11 +84,11 @@ export function watch<T>(
     ? () => source.map(s => (isRef(s) ? s.value : s()))
     : isRef(source)
       ? () => source.value
-      : source
+      : () => source(registerCleanup)
   const getter = deep ? () => traverse(baseGetter()) : baseGetter
 
   let cleanup: any
-  const registerCleanup = (fn: () => void) => {
+  const registerCleanup: CleanupRegistrator = (fn: () => void) => {
     // TODO wrap the cleanup fn for error handling
     cleanup = runner.onStop = fn
   }