]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types): ensure nextTick return type reflect correct Promise value (#8406)
author丶远方 <yangpanteng@gmail.com>
Tue, 11 Jul 2023 09:56:02 +0000 (17:56 +0800)
committerGitHub <noreply@github.com>
Tue, 11 Jul 2023 09:56:02 +0000 (17:56 +0800)
packages/runtime-core/__tests__/scheduler.spec.ts
packages/runtime-core/src/scheduler.ts
packages/shared/src/typeUtils.ts

index c06b9afb3e354d9edcb166f1de2ce143d1575c30..6246a87e8f73435e3444635cf5420bfab22e05b9 100644 (file)
@@ -546,4 +546,16 @@ describe('scheduler', () => {
     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)
+  })
 })
index 923f3ec8251f3e3c2249ea9a10f298bae982359b..64c70ab59ca06fe2b7f0059bc85c5fa71686858b 100644 (file)
@@ -1,5 +1,5 @@
 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'
 
@@ -50,10 +50,10 @@ let currentFlushPromise: Promise<void> | null = null
 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
 }
index 67fb47c23b3a1aff358d09e5791266255ced66a4..1deb47291252a347846eadc34e4f1296eee776b5 100644 (file)
@@ -12,3 +12,12 @@ export type LooseRequired<T> = { [P in keyof (T & Required<T>)]: T[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