From be3bd0bbfeef9ede20d7605b1d07a648df87dbda Mon Sep 17 00:00:00 2001 From: Carlos Rodrigues Date: Fri, 6 May 2022 10:07:49 +0100 Subject: [PATCH] fix(types): keep the original type when unwrapping `markRaw` (#3791) --- packages/reactivity/src/reactive.ts | 6 +++-- packages/reactivity/src/ref.ts | 2 ++ test-dts/index.d.ts | 6 ++--- test-dts/reactivity.test-d.ts | 42 +++++++++++++++++++++++++++-- 4 files changed, 49 insertions(+), 7 deletions(-) diff --git a/packages/reactivity/src/reactive.ts b/packages/reactivity/src/reactive.ts index f160b21110d..ce689012da8 100644 --- a/packages/reactivity/src/reactive.ts +++ b/packages/reactivity/src/reactive.ts @@ -11,7 +11,7 @@ import { shallowCollectionHandlers, shallowReadonlyCollectionHandlers } from './collectionHandlers' -import { UnwrapRefSimple, Ref } from './ref' +import { UnwrapRefSimple, Ref, RawSymbol } from './ref' export const enum ReactiveFlags { SKIP = '__v_skip', @@ -241,7 +241,9 @@ export function toRaw(observed: T): T { return raw ? toRaw(raw) : observed } -export function markRaw(value: T): T { +export function markRaw( + value: T +): T & { [RawSymbol]?: true } { def(value, ReactiveFlags.SKIP, true) return value } diff --git a/packages/reactivity/src/ref.ts b/packages/reactivity/src/ref.ts index 22dd432b945..2a3b3732e0e 100644 --- a/packages/reactivity/src/ref.ts +++ b/packages/reactivity/src/ref.ts @@ -12,6 +12,7 @@ import { CollectionTypes } from './collectionHandlers' import { createDep, Dep } from './dep' declare const RefSymbol: unique symbol +export declare const RawSymbol: unique symbol export interface Ref { value: T @@ -291,6 +292,7 @@ export type UnwrapRefSimple = T extends | BaseTypes | Ref | RefUnwrapBailTypes[keyof RefUnwrapBailTypes] + | { [RawSymbol]?: true } ? T : T extends Array ? { [K in keyof T]: UnwrapRefSimple } diff --git a/test-dts/index.d.ts b/test-dts/index.d.ts index 59eadcb92d9..d0eeb6a7b65 100644 --- a/test-dts/index.d.ts +++ b/test-dts/index.d.ts @@ -9,9 +9,9 @@ export function expectType(value: T): void export function expectError(value: T): void export function expectAssignable(value: T2): void -export type IsUnion = (T extends any - ? (U extends T ? false : true) - : never) extends false +export type IsUnion = ( + T extends any ? (U extends T ? false : true) : never +) extends false ? false : true diff --git a/test-dts/reactivity.test-d.ts b/test-dts/reactivity.test-d.ts index 4c22765e742..0499c6da287 100644 --- a/test-dts/reactivity.test-d.ts +++ b/test-dts/reactivity.test-d.ts @@ -1,5 +1,14 @@ -import { shallowReadonly } from '@vue/reactivity' -import { ref, readonly, describe, expectError, expectType, Ref } from './index' +import { + ref, + readonly, + shallowReadonly, + describe, + expectError, + expectType, + Ref, + reactive, + markRaw +} from './index' describe('should support DeepReadonly', () => { const r = readonly({ obj: { k: 'v' } }) @@ -15,6 +24,35 @@ describe('readonly ref', () => { expectType(r) }) +describe('should support markRaw', () => { + class Test { + item = {} as Ref + } + const test = new Test() + const plain = { + ref: ref(1) + } + + const r = reactive({ + class: { + raw: markRaw(test), + reactive: test + }, + plain: { + raw: markRaw(plain), + reactive: plain + } + }) + + expectType>(r.class.raw) + // @ts-expect-error it should unwrap + expectType>(r.class.reactive) + + expectType>(r.plain.raw.ref) + // @ts-expect-error it should unwrap + expectType>(r.plain.reactive.ref) +}) + describe('shallowReadonly ref unwrap', () => { const r = shallowReadonly({ count: { n: ref(1) } }) // @ts-expect-error