]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(types): properly infer return type from async setup (#2051)
authorHcySunYang <HcySunYang@outlook.com>
Mon, 14 Sep 2020 15:28:56 +0000 (23:28 +0800)
committerGitHub <noreply@github.com>
Mon, 14 Sep 2020 15:28:56 +0000 (11:28 -0400)
fix #2049

packages/runtime-core/src/apiDefineComponent.ts
packages/runtime-core/src/componentOptions.ts
packages/runtime-core/src/componentPublicInstance.ts
test-dts/defineComponent.test-d.tsx

index eda62eaab03adc299822f6f6d43289806e29eeaf..c054e65a8eb380bf615304af5790c29243706557 100644 (file)
@@ -5,7 +5,8 @@ import {
   ComponentOptionsWithArrayProps,
   ComponentOptionsWithObjectProps,
   ComponentOptionsMixin,
-  RenderFunction
+  RenderFunction,
+  UnwrapAsyncBindings
 } from './componentOptions'
 import {
   SetupContext,
@@ -37,7 +38,7 @@ export function defineComponent<Props, RawBindings = object>(
 ): ComponentPublicInstanceConstructor<
   CreateComponentPublicInstance<
     Props,
-    RawBindings,
+    UnwrapAsyncBindings<RawBindings>,
     {},
     {},
     {},
@@ -78,7 +79,7 @@ export function defineComponent<
 ): ComponentPublicInstanceConstructor<
   CreateComponentPublicInstance<
     Props,
-    RawBindings,
+    UnwrapAsyncBindings<RawBindings>,
     D,
     C,
     M,
@@ -130,7 +131,7 @@ export function defineComponent<
   // but now we can export array props in TSX
   CreateComponentPublicInstance<
     Readonly<{ [key in PropNames]?: any }>,
-    RawBindings,
+    UnwrapAsyncBindings<RawBindings>,
     D,
     C,
     M,
@@ -181,7 +182,7 @@ export function defineComponent<
 ): ComponentPublicInstanceConstructor<
   CreateComponentPublicInstance<
     ExtractPropTypes<PropsOptions, false>,
-    RawBindings,
+    UnwrapAsyncBindings<RawBindings>,
     D,
     C,
     M,
index 0eb24a6c2a13a235af5bce9747cc52f5ce2d5c46..d02a1bb0bdc6ffb3e3c559cbc15e10781b617410 100644 (file)
@@ -72,6 +72,8 @@ export interface ComponentCustomOptions {}
 
 export type RenderFunction = () => VNodeChild
 
+export type UnwrapAsyncBindings<T> = T extends Promise<infer S> ? S : T
+
 export interface ComponentOptionsBase<
   Props,
   RawBindings,
index 695e5ace3c901020c361e8f038db7eb85144074a..77fcbeeae26d39c0271e7daf31c4213794ba6b2c 100644 (file)
@@ -27,7 +27,8 @@ import {
   OptionTypesType,
   OptionTypesKeys,
   resolveMergedOptions,
-  isInBeforeCreate
+  isInBeforeCreate,
+  UnwrapAsyncBindings
 } from './componentOptions'
 import { EmitsOptions, EmitFn } from './componentEmits'
 import { Slots } from './componentSlots'
@@ -168,7 +169,7 @@ export type ComponentPublicInstance<
     options?: WatchOptions
   ): WatchStopHandle
 } & P &
-  ShallowUnwrapRef<B> &
+  ShallowUnwrapRef<UnwrapAsyncBindings<B>> &
   D &
   ExtractComputedReturns<C> &
   M &
index 18c3338abeb0cd1b4069a042f3053eb3063e2d0e..59d6a3bcb2818145481d902681d61aaa238f0a9a 100644 (file)
@@ -864,3 +864,39 @@ describe('extract instance type', () => {
   //  @ts-expect-error
   expectError((compA.baseA = 1))
 })
+
+describe('async setup', () => {
+  type GT = string & { __brand: unknown }
+  const Comp = defineComponent({
+    async setup() {
+      // setup context
+      return {
+        a: ref(1),
+        b: {
+          c: ref('hi')
+        },
+        d: reactive({
+          e: ref('hello' as GT)
+        })
+      }
+    },
+    render() {
+      // assert setup context unwrapping
+      expectType<number>(this.a)
+      expectType<string>(this.b.c.value)
+      expectType<GT>(this.d.e)
+
+      // setup context properties should be mutable
+      this.a = 2
+    }
+  })
+
+  const vm = {} as InstanceType<typeof Comp>
+  // assert setup context unwrapping
+  expectType<number>(vm.a)
+  expectType<string>(vm.b.c.value)
+  expectType<GT>(vm.d.e)
+
+  // setup context properties should be mutable
+  vm.a = 2
+})