Skip to content

types(reactivity): fix the return type error when the toRaw parameter type is readonly #9124

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Next Next commit
types(reactivity): fix the return type error when the toRaw parameter…
… type is readonly
  • Loading branch information
Alfred-Skyblue committed Sep 4, 2023
commit 864e566d089054a30ee2d9bfb86e20ebaca863b0
30 changes: 29 additions & 1 deletion packages/dts-test/reactivity.test-d.ts
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down Expand Up @@ -62,3 +70,23 @@ describe('should unwrap tuple correctly', () => {
const reactiveTuple = reactive(tuple)
expectType<Ref<number>>(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<Foo>(rawObj)

// shallowReadonly
const shallowR = shallowReadonly(foo)
const shallowRawObj = toRaw(shallowR)
expectType<Foo>(shallowRawObj)
})
19 changes: 17 additions & 2 deletions packages/reactivity/src/reactive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ export const enum ReactiveFlags {
RAW = '__v_raw'
}

declare const ReadonlyRawType: unique symbol

interface ReadonlyRaw<T> {
/**
* Original type used to hold readonly function parameters
*/
[ReadonlyRawType]: T
}

export interface Target {
[ReactiveFlags.SKIP]?: boolean
[ReactiveFlags.IS_REACTIVE]?: boolean
Expand Down Expand Up @@ -195,7 +204,7 @@ export type DeepReadonly<T> = T extends Builtin
*/
export function readonly<T extends object>(
target: T
): DeepReadonly<UnwrapNestedRefs<T>> {
): DeepReadonly<UnwrapNestedRefs<T>> & ReadonlyRaw<T> {
return createReactiveObject(
target,
true,
Expand Down Expand Up @@ -235,7 +244,9 @@ export function readonly<T extends object>(
* @param target - The source object.
* @see {@link https://vuejs.org/api/reactivity-advanced.html#shallowreadonly}
*/
export function shallowReadonly<T extends object>(target: T): Readonly<T> {
export function shallowReadonly<T extends object>(
target: T
): Readonly<T> & ReadonlyRaw<T> {
return createReactiveObject(
target,
true,
Expand Down Expand Up @@ -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<T extends ReadonlyRaw<any>>(
observed: T
): T[typeof ReadonlyRawType]
export function toRaw<T>(observed: T): T
export function toRaw<T>(observed: T): T {
const raw = observed && (observed as Target)[ReactiveFlags.RAW]
return raw ? toRaw(raw) : observed
Expand Down
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy