diff --git a/packages/runtime-core/src/componentProxy.ts b/packages/runtime-core/src/componentProxy.ts index 4582496e442..9e451110523 100644 --- a/packages/runtime-core/src/componentProxy.ts +++ b/packages/runtime-core/src/componentProxy.ts @@ -8,7 +8,13 @@ import { ComputedOptions, MethodOptions } from './apiOptions' -import { UnwrapRef, ReactiveEffect, isRef, isReactive } from '@vue/reactivity' +import { + ReactiveEffect, + isRef, + isReactive, + Ref, + ComputedRef +} from '@vue/reactivity' import { warn } from './warning' import { Slots } from './componentSlots' import { @@ -19,9 +25,9 @@ import { // public properties exposed on the proxy, which is used as the render context // in templates (as `this` in the render option) export type ComponentPublicInstance< - P = {}, - B = {}, - D = {}, + P = {}, // props type extracted from props option + B = {}, // raw bindings returned from setup() + D = {}, // return from data() C extends ComputedOptions = {}, M extends MethodOptions = {}, PublicProps = P @@ -40,11 +46,17 @@ export type ComponentPublicInstance< $nextTick: typeof nextTick $watch: typeof instanceWatch } & P & - UnwrapRef & + UnwrapSetupBindings & D & ExtractComputedReturns & M +type UnwrapSetupBindings = { [K in keyof B]: UnwrapBinding } + +type UnwrapBinding = B extends ComputedRef + ? B extends ComputedRef ? V : B + : B extends Ref ? V : B + const publicPropertiesMap: Record< string, (i: ComponentInternalInstance) => any diff --git a/test-dts/defineComponent.test-d.tsx b/test-dts/defineComponent.test-d.tsx index 417df9d1a5a..a9e7e427ee6 100644 --- a/test-dts/defineComponent.test-d.tsx +++ b/test-dts/defineComponent.test-d.tsx @@ -1,5 +1,13 @@ import { expectError, expectType } from 'tsd' -import { describe, defineComponent, PropType, ref, createApp } from './index' +import { + describe, + defineComponent, + PropType, + ref, + Ref, + reactive, + createApp +} from './index' describe('with object props', () => { interface ExpectedProps { @@ -57,11 +65,14 @@ describe('with object props', () => { // setup context return { c: ref(1), - d: { + d: reactive({ e: ref('hi') - }, - f: { + }), + f: reactive({ g: ref('hello' as GT) + }), + h: { + i: ref('hi') } } }, @@ -95,6 +106,9 @@ describe('with object props', () => { expectType(this.d.e) expectType(this.f.g) + // should not unwrap refs nested under non-reactive objects + expectType>(this.h.i) + // setup context properties should be mutable this.c = 2