await nextTick()
expect(spy).toHaveBeenCalledTimes(1)
})
+
+ it('nextTick should return promise', async () => {
+ const fn = vi.fn(() => {
+ return 1
+ })
+
+ const p = nextTick(fn)
+
+ expect(p).toBeInstanceOf(Promise)
+ expect(await p).toBe(1)
+ expect(fn).toHaveBeenCalledTimes(1)
+ })
})
import { ErrorCodes, callWithErrorHandling } from './errorHandling'
-import { isArray, NOOP } from '@vue/shared'
+import { Awaited, isArray, NOOP } from '@vue/shared'
import { ComponentInternalInstance, getComponentName } from './component'
import { warn } from './warning'
const RECURSION_LIMIT = 100
type CountMap = Map<SchedulerJob, number>
-export function nextTick<T = void>(
+export function nextTick<T = void, R = void>(
this: T,
- fn?: (this: T) => void
-): Promise<void> {
+ fn?: (this: T) => R
+): Promise<Awaited<R>> {
const p = currentFlushPromise || resolvedPromise
return fn ? p.then(this ? fn.bind(this) : fn) : p
}
// If the type T accepts type "any", output type Y, otherwise output type N.
// https://stackoverflow.com/questions/49927523/disallow-call-with-any/49928360#49928360
export type IfAny<T, Y, N> = 0 extends 1 & T ? Y : N
+
+// To prevent users with TypeScript versions lower than 4.5 from encountering unsupported Awaited<T> type, a copy has been made here.
+export type Awaited<T> = T extends null | undefined
+ ? T // special case for `null | undefined` when not in `--strictNullChecks` mode
+ : T extends object & { then(onfulfilled: infer F, ...args: infer _): any } // `await` only unwraps object types with a callable `then`. Non-object types are not unwrapped
+ ? F extends (value: infer V, ...args: infer _) => any // if the argument to `then` is callable, extracts the first argument
+ ? Awaited<V> // recursively unwrap the value
+ : never // the argument to `then` was not callable
+ : T // non-object or non-thenable