From 864e566d089054a30ee2d9bfb86e20ebaca863b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B6=E8=BF=9C=E6=96=B9?= Date: Mon, 4 Sep 2023 11:43:41 +0800 Subject: [PATCH 1/3] types(reactivity): fix the return type error when the toRaw parameter type is readonly --- packages/dts-test/reactivity.test-d.ts | 30 +++++++++++++++++++++++++- packages/reactivity/src/reactive.ts | 19 ++++++++++++++-- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/dts-test/reactivity.test-d.ts b/packages/dts-test/reactivity.test-d.ts index 4504f9e352d..d3821bf7565 100644 --- a/packages/dts-test/reactivity.test-d.ts +++ b/packages/dts-test/reactivity.test-d.ts @@ -1,4 +1,12 @@ -import { ref, readonly, shallowReadonly, Ref, reactive, markRaw } from 'vue' +import { + ref, + readonly, + shallowReadonly, + Ref, + reactive, + markRaw, + toRaw +} from 'vue' import { describe, expectType } from './utils' describe('should support DeepReadonly', () => { @@ -62,3 +70,23 @@ describe('should unwrap tuple correctly', () => { const reactiveTuple = reactive(tuple) expectType>(reactiveTuple[0]) }) + +// #7478 +describe('readonly raw type', () => { + type Foo = { readonly a: number; b: string; c: { d: number } } + const foo: Foo = { + a: 1, + b: 'b', + c: { d: 2 } + } + + // readonly + const r = readonly(foo) + const rawObj = toRaw(r) + expectType(rawObj) + + // shallowReadonly + const shallowR = shallowReadonly(foo) + const shallowRawObj = toRaw(shallowR) + expectType(shallowRawObj) +}) diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index 1881955cf1c..1e30c5d8c97 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -21,6 +21,15 @@ export const enum ReactiveFlags { RAW = '__v_raw' } +declare const ReadonlyRawType: unique symbol + +interface ReadonlyRaw { + /** + * Original type used to hold readonly function parameters + */ + [ReadonlyRawType]: T +} + export interface Target { [ReactiveFlags.SKIP]?: boolean [ReactiveFlags.IS_REACTIVE]?: boolean @@ -195,7 +204,7 @@ export type DeepReadonly = T extends Builtin */ export function readonly( target: T -): DeepReadonly> { +): DeepReadonly> & ReadonlyRaw { return createReactiveObject( target, true, @@ -235,7 +244,9 @@ export function readonly( * @param target - The source object. * @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowreadonly} */ -export function shallowReadonly(target: T): Readonly { +export function shallowReadonly( + target: T +): Readonly & ReadonlyRaw { return createReactiveObject( target, true, @@ -362,6 +373,10 @@ export function isProxy(value: unknown): boolean { * @param observed - The object for which the "raw" value is requested. * @see {@link https://vuejs.org/api/reactivity-advanced.html#toraw} */ +export function toRaw>( + observed: T +): T[typeof ReadonlyRawType] +export function toRaw(observed: T): T export function toRaw(observed: T): T { const raw = observed && (observed as Target)[ReactiveFlags.RAW] return raw ? toRaw(raw) : observed From 0cae446b8e6adca1c5f4444a4a57fd72098cec06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B6=E8=BF=9C=E6=96=B9?= Date: Wed, 6 Dec 2023 23:37:58 +0800 Subject: [PATCH 2/3] chore: rename `ReadonlyRawType` to `ReadonlyRawSymbol` --- packages/reactivity/src/reactive.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index dcce3d7470f..30f9ee14cee 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -21,13 +21,13 @@ export const enum ReactiveFlags { RAW = '__v_raw' } -declare const ReadonlyRawType: unique symbol +declare const ReadonlyRawSymbol: unique symbol interface ReadonlyRaw { /** * Original type used to hold readonly function parameters */ - [ReadonlyRawType]: T + [ReadonlyRawSymbol]: T } export interface Target { @@ -375,7 +375,7 @@ export function isProxy(value: unknown): boolean { */ export function toRaw>( observed: T -): T[typeof ReadonlyRawType] +): T[typeof ReadonlyRawSymbol] export function toRaw(observed: T): T export function toRaw(observed: T): T { const raw = observed && (observed as Target)[ReactiveFlags.RAW] From 221b27d79c33033e99820e4b36213c3ab64868a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=B6=E8=BF=9C=E6=96=B9?= Date: Thu, 10 Oct 2024 17:09:17 +0800 Subject: [PATCH 3/3] chore: update type --- packages-private/dts-test/reactivity.test-d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages-private/dts-test/reactivity.test-d.ts b/packages-private/dts-test/reactivity.test-d.ts index ff1b82c9715..eeded3a7be6 100644 --- a/packages-private/dts-test/reactivity.test-d.ts +++ b/packages-private/dts-test/reactivity.test-d.ts @@ -134,7 +134,7 @@ describe('should not error when assignment', () => { // #7478 describe('readonly raw type', () => { - type Foo = { readonly a: number; b: string; c: { d: number } } + type Foo = { a: number; b: string; c: { d: number } } const foo: Foo = { a: 1, b: 'b',