import { Ref, ref, shallowRef, isRef, unref, reactive, expectType, proxyRefs, toRef, toRefs, ToRefs, shallowReactive } from './index' function plainType(arg: number | Ref) { // ref coercing const coerced = ref(arg) expectType>(coerced) // isRef as type guard if (isRef(arg)) { expectType>(arg) } // ref unwrapping expectType(unref(arg)) // ref inner type should be unwrapped const nestedRef = ref({ foo: ref(1) }) expectType<{ foo: number }>(nestedRef.value) // ref boolean const falseRef = ref(false) expectType>(falseRef) expectType(falseRef.value) // ref true const trueRef = ref(true) expectType>(trueRef) expectType(trueRef.value) // tuple expectType<[number, string]>(unref(ref([1, '1']))) interface IteratorFoo { [Symbol.iterator]: any } // with symbol expectType>( ref() ) // should not unwrap ref inside arrays const arr = ref([1, new Map(), ref('1')]).value const value = arr[0] if (isRef(value)) { expectType(value) } else if (typeof value === 'number') { expectType(value) } else { // should narrow down to Map type // and not contain any Ref type expectType>(value) } // should still unwrap in objects nested in arrays const arr2 = ref([{ a: ref(1) }]).value expectType(arr2[0].a) } plainType(1) function bailType(arg: HTMLElement | Ref) { // ref coercing const coerced = ref(arg) expectType>(coerced) // isRef as type guard if (isRef(arg)) { expectType>(arg) } // ref unwrapping expectType(unref(arg)) // ref inner type should be unwrapped // eslint-disable-next-line no-restricted-globals const nestedRef = ref({ foo: ref(document.createElement('DIV')) }) expectType>(nestedRef) expectType<{ foo: HTMLElement }>(nestedRef.value) } // eslint-disable-next-line no-restricted-globals const el = document.createElement('DIV') bailType(el) function withSymbol() { const customSymbol = Symbol() const obj = { [Symbol.asyncIterator]: ref(1), [Symbol.hasInstance]: { a: ref('a') }, [Symbol.isConcatSpreadable]: { b: ref(true) }, [Symbol.iterator]: [ref(1)], [Symbol.match]: new Set>(), [Symbol.matchAll]: new Map>(), [Symbol.replace]: { arr: [ref('a')] }, [Symbol.search]: { set: new Set>() }, [Symbol.species]: { map: new Map>() }, [Symbol.split]: new WeakSet>(), [Symbol.toPrimitive]: new WeakMap, string>(), [Symbol.toStringTag]: { weakSet: new WeakSet>() }, [Symbol.unscopables]: { weakMap: new WeakMap, string>() }, [customSymbol]: { arr: [ref(1)] } } const objRef = ref(obj) expectType>(objRef.value[Symbol.asyncIterator]) expectType<{ a: Ref }>(objRef.value[Symbol.hasInstance]) expectType<{ b: Ref }>(objRef.value[Symbol.isConcatSpreadable]) expectType[]>(objRef.value[Symbol.iterator]) expectType>>(objRef.value[Symbol.match]) expectType>>(objRef.value[Symbol.matchAll]) expectType<{ arr: Ref[] }>(objRef.value[Symbol.replace]) expectType<{ set: Set> }>(objRef.value[Symbol.search]) expectType<{ map: Map> }>(objRef.value[Symbol.species]) expectType>>(objRef.value[Symbol.split]) expectType, string>>(objRef.value[Symbol.toPrimitive]) expectType<{ weakSet: WeakSet> }>( objRef.value[Symbol.toStringTag] ) expectType<{ weakMap: WeakMap, string> }>( objRef.value[Symbol.unscopables] ) expectType<{ arr: Ref[] }>(objRef.value[customSymbol]) } withSymbol() const state = reactive({ foo: { value: 1, label: 'bar' } }) expectType(state.foo.label) // shallowRef type Status = 'initial' | 'ready' | 'invalidating' const shallowStatus = shallowRef('initial') if (shallowStatus.value === 'initial') { expectType>(shallowStatus) expectType(shallowStatus.value) shallowStatus.value = 'invalidating' } const refStatus = ref('initial') if (refStatus.value === 'initial') { expectType>(shallowStatus) expectType(shallowStatus.value) refStatus.value = 'invalidating' } // proxyRefs: should return `reactive` directly const r1 = reactive({ k: 'v' }) const p1 = proxyRefs(r1) expectType(p1) // proxyRefs: `ShallowUnwrapRef` const r2 = { a: ref(1), obj: { k: ref('foo') } } const p2 = proxyRefs(r2) expectType(p2.a) expectType>(p2.obj.k) // toRef and toRefs { const obj: { a: number b: Ref c: number | string } = { a: 1, b: ref(1), c: 1 } // toRef expectType>(toRef(obj, 'a')) expectType>(toRef(obj, 'b')) // Should not distribute Refs over union expectType>(toRef(obj, 'c')) // toRefs expectType<{ a: Ref b: Ref // Should not distribute Refs over union c: Ref }>(toRefs(obj)) // Both should not do any unwrapping const someReactive = shallowReactive({ a: { b: ref(42) } }) const toRefResult = toRef(someReactive, 'a') const toRefsResult = toRefs(someReactive) expectType>(toRefResult.value.b) expectType>(toRefsResult.a.value.b) } // toRef default value { const obj: { x?: number } = {} const x = toRef(obj, 'x', 1) expectType>(x) } // #2687 interface AppData { state: 'state1' | 'state2' | 'state3' } const data: ToRefs = toRefs( reactive({ state: 'state1' }) ) switch (data.state.value) { case 'state1': data.state.value = 'state2' break case 'state2': data.state.value = 'state3' break case 'state3': data.state.value = 'state1' break } // #3954 function testUnrefGenerics(p: T | Ref) { expectType(unref(p)) } testUnrefGenerics(1) // #4771 describe('shallow reactive in reactive', () => { const baz = reactive({ foo: shallowReactive({ a: { b: ref(42) } }) }) const foo = toRef(baz, 'foo') expectType>(foo.value.a.b) expectType(foo.value.a.b.value) }) describe('shallow ref in reactive', () => { const x = reactive({ foo: shallowRef({ bar: { baz: ref(123), qux: reactive({ z: ref(123) }) } }) }) expectType>(x.foo.bar.baz) expectType(x.foo.bar.qux.z) }) describe('ref in shallow ref', () => { const x = shallowRef({ a: ref(123) }) expectType>(x.value.a) }) describe('reactive in shallow ref', () => { const x = shallowRef({ a: reactive({ b: ref(0) }) }) expectType(x.value.a.b) })