]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
types(watch): better typing when watching multiple sources (#2425)
authorZcating <zcating@Qq.com>
Fri, 4 Dec 2020 21:32:26 +0000 (05:32 +0800)
committerGitHub <noreply@github.com>
Fri, 4 Dec 2020 21:32:26 +0000 (16:32 -0500)
packages/runtime-core/src/apiWatch.ts
test-dts/watch.test-d.ts

index af54568823f17fe87c50b862a23160e41f43ddca..f0ff31fcfdd78f5a3398d1121bfb9181725de99d 100644 (file)
@@ -78,15 +78,26 @@ export function watchEffect(
 // initial value for watchers to trigger on undefined initial values
 const INITIAL_WATCHER_VALUE = {}
 
+type MultiWatchSources = (WatchSource<unknown> | object)[]
+
 // overload #1: array of multiple sources + cb
-// Readonly constraint helps the callback to correctly infer value types based
-// on position in the source array. Otherwise the values will get a union type
-// of all possible value types.
 export function watch<
-  T extends Readonly<Array<WatchSource<unknown> | object>>,
+  T extends MultiWatchSources,
   Immediate extends Readonly<boolean> = false
 >(
-  sources: T,
+  sources: [...T],
+  cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
+  options?: WatchOptions<Immediate>
+): WatchStopHandle
+
+// overload #2 for multiple sources w/ `as const`
+// watch([foo, bar] as const, () => {})
+// somehow [...T] breaks when the type is readonly
+export function watch<
+  T extends Readonly<MultiWatchSources>,
+  Immediate extends Readonly<boolean> = false
+>(
+  source: T,
   cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
   options?: WatchOptions<Immediate>
 ): WatchStopHandle
index 84c6e542b5a79ca64655d15d21c38b943832808e..52d26c93c4c51ed170cbddc7331d60f9baf263e3 100644 (file)
@@ -11,8 +11,8 @@ watch(source, (value, oldValue) => {
 })
 
 watch([source, source2, source3], (values, oldValues) => {
-  expectType<(string | number)[]>(values)
-  expectType<(string | number)[]>(oldValues)
+  expectType<[string, string, number]>(values)
+  expectType<[string, string, number]>(oldValues)
 })
 
 // const array
@@ -34,8 +34,10 @@ watch(
 watch(
   [source, source2, source3],
   (values, oldValues) => {
-    expectType<(string | number)[]>(values)
-    expectType<(string | number | undefined)[]>(oldValues)
+    expectType<[string, string, number]>(values)
+    expectType<[string | undefined, string | undefined, number | undefined]>(
+      oldValues
+    )
   },
   { immediate: true }
 )
@@ -61,3 +63,15 @@ watch(nestedRefSource, (v, ov) => {
   expectType<{ foo: number }>(v)
   expectType<{ foo: number }>(ov)
 })
+
+const someRef = ref({ test: 'test' })
+const otherRef = ref({ a: 'b' })
+watch([someRef, otherRef], values => {
+  const value1 = values[0]
+  // no type error
+  console.log(value1.test)
+
+  const value2 = values[1]
+  // no type error
+  console.log(value2.a)
+})