types(watch): better typing when watching multiple sources (#2425)

This commit is contained in:
Zcating 2020-12-05 05:32:26 +08:00 committed by GitHub
parent 47b3652ecd
commit d2d27b2e66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 9 deletions

View 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

View 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)
})