From 146fb1c6719e7ac67c1f290e3e2194cc643cde0b Mon Sep 17 00:00:00 2001 From: tycho Date: Tue, 31 Oct 2023 11:09:27 +0800 Subject: [PATCH] feat(reactivity): enhance type inference for context-sensitive inputs --- packages/dts-test/reactivity.test-d.ts | 31 +++++++++++++++++++++++++- packages/reactivity/src/reactive.ts | 5 +++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/dts-test/reactivity.test-d.ts b/packages/dts-test/reactivity.test-d.ts index 4504f9e352d..8dff81809b3 100644 --- a/packages/dts-test/reactivity.test-d.ts +++ b/packages/dts-test/reactivity.test-d.ts @@ -1,4 +1,13 @@ -import { ref, readonly, shallowReadonly, Ref, reactive, markRaw } from 'vue' +import { + ref, + readonly, + shallowReadonly, + Ref, + reactive, + markRaw, + ComputedRef, + computed +} from 'vue' import { describe, expectType } from './utils' describe('should support DeepReadonly', () => { @@ -62,3 +71,23 @@ describe('should unwrap tuple correctly', () => { const reactiveTuple = reactive(tuple) expectType>(reactiveTuple[0]) }) + +// #1930 +describe('should unwrap the computed type', () => { + interface Bar { + a: number + b: (_: any) => void + } + + const computedA: ComputedRef = computed(() => 1) + + expectType<{ a: number }>(reactive({ a: computedA })) + + expectType( + reactive({ + a: computedA, // issue happens here, but is should be okay + // @ts-expect-error + b: _ => {} // error depending on --noImplicitAny + }) + ) +}) diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index 1881955cf1c..f31bfeae20b 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -64,6 +64,8 @@ function getTargetType(value: Target) { // only unwrap nested ref export type UnwrapNestedRefs = T extends Ref ? T : UnwrapRefSimple +type NoInfer = [T][T extends any ? 0 : never] + /** * Returns a reactive proxy of the object. * @@ -80,6 +82,9 @@ export type UnwrapNestedRefs = T extends Ref ? T : UnwrapRefSimple * @see {@link https://vuejs.org/api/reactivity-core.html#reactive} */ export function reactive(target: T): UnwrapNestedRefs +export function reactive( + target: T +): NoInfer> export function reactive(target: object) { // if trying to observe a readonly proxy, return the readonly version. if (isReadonly(target)) {