// 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
})
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
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 }
)
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)
+})