fix(types): should unwrap tuple correctly (#3820)

fix #3819
This commit is contained in:
HeYunfei 2022-10-26 16:27:42 +08:00 committed by GitHub
parent 09bb3e996e
commit e816812f10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 70 deletions

View File

@ -280,13 +280,10 @@ export interface RefUnwrapBailTypes {}
export type ShallowUnwrapRef<T> = { export type ShallowUnwrapRef<T> = {
[K in keyof T]: T[K] extends Ref<infer V> [K in keyof T]: T[K] extends Ref<infer V>
? V ? V // if `V` is `unknown` that means it does not extend `Ref` and is undefined
: // if `V` is `unknown` that means it does not extend `Ref` and is undefined : T[K] extends Ref<infer V> | undefined
T[K] extends Ref<infer V> | undefined ? unknown extends V ? undefined : V | undefined
? unknown extends V : T[K]
? undefined
: V | undefined
: T[K]
} }
export type UnwrapRef<T> = T extends ShallowRef<infer V> export type UnwrapRef<T> = T extends ShallowRef<infer V>
@ -303,7 +300,7 @@ export type UnwrapRefSimple<T> = T extends
| RefUnwrapBailTypes[keyof RefUnwrapBailTypes] | RefUnwrapBailTypes[keyof RefUnwrapBailTypes]
| { [RawSymbol]?: true } | { [RawSymbol]?: true }
? T ? T
: T extends Array<any> : T extends ReadonlyArray<any>
? { [K in keyof T]: UnwrapRefSimple<T[K]> } ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
: T extends object & { [ShallowReactiveMarker]?: never } : T extends object & { [ShallowReactiveMarker]?: never }
? { ? {

View File

@ -1,62 +1,73 @@
import { import {
ref, ref,
readonly, readonly,
shallowReadonly, shallowReadonly,
describe, describe,
expectError, expectError,
expectType, expectType,
Ref, Ref,
reactive, reactive,
markRaw markRaw
} from './index' } from './index'
describe('should support DeepReadonly', () => { describe('should support DeepReadonly', () => {
const r = readonly({ obj: { k: 'v' } }) const r = readonly({ obj: { k: 'v' } })
// @ts-expect-error // @ts-expect-error
expectError((r.obj = {})) expectError((r.obj = {}))
// @ts-expect-error // @ts-expect-error
expectError((r.obj.k = 'x')) expectError((r.obj.k = 'x'))
}) })
// #4180 // #4180
describe('readonly ref', () => { describe('readonly ref', () => {
const r = readonly(ref({ count: 1 })) const r = readonly(ref({ count: 1 }))
expectType<Ref>(r) expectType<Ref>(r)
}) })
describe('should support markRaw', () => { describe('should support markRaw', () => {
class Test<T> { class Test<T> {
item = {} as Ref<T> item = {} as Ref<T>
} }
const test = new Test<number>() const test = new Test<number>()
const plain = { const plain = {
ref: ref(1) ref: ref(1)
} }
const r = reactive({ const r = reactive({
class: { class: {
raw: markRaw(test), raw: markRaw(test),
reactive: test reactive: test
}, },
plain: { plain: {
raw: markRaw(plain), raw: markRaw(plain),
reactive: plain reactive: plain
} }
}) })
expectType<Test<number>>(r.class.raw) expectType<Test<number>>(r.class.raw)
// @ts-expect-error it should unwrap // @ts-expect-error it should unwrap
expectType<Test<number>>(r.class.reactive) expectType<Test<number>>(r.class.reactive)
expectType<Ref<number>>(r.plain.raw.ref) expectType<Ref<number>>(r.plain.raw.ref)
// @ts-expect-error it should unwrap // @ts-expect-error it should unwrap
expectType<Ref<number>>(r.plain.reactive.ref) expectType<Ref<number>>(r.plain.reactive.ref)
}) })
describe('shallowReadonly ref unwrap', () => { describe('shallowReadonly ref unwrap', () => {
const r = shallowReadonly({ count: { n: ref(1) } }) const r = shallowReadonly({ count: { n: ref(1) } })
// @ts-expect-error // @ts-expect-error
r.count = 2 r.count = 2
expectType<Ref>(r.count.n) expectType<Ref>(r.count.n)
r.count.n.value = 123 r.count.n.value = 123
}) })
// #3819
describe('should unwrap tuple correctly', () => {
const readonlyTuple = [ref(0)] as const
const reactiveReadonlyTuple = reactive(readonlyTuple)
expectType<Ref<number>>(reactiveReadonlyTuple[0])
const tuple: [Ref<number>] = [ref(0)]
const reactiveTuple = reactive(tuple)
expectType<Ref<number>>(reactiveTuple[0])
})