ref.test-d.ts 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. import {
  2. Ref,
  3. ref,
  4. shallowRef,
  5. isRef,
  6. unref,
  7. reactive,
  8. expectType,
  9. proxyRefs,
  10. toRef,
  11. toRefs,
  12. ToRefs,
  13. shallowReactive,
  14. watch
  15. } from './index'
  16. function plainType(arg: number | Ref<number>) {
  17. // ref coercing
  18. const coerced = ref(arg)
  19. expectType<Ref<number>>(coerced)
  20. // isRef as type guard
  21. if (isRef(arg)) {
  22. expectType<Ref<number>>(arg)
  23. }
  24. // ref unwrapping
  25. expectType<number>(unref(arg))
  26. // ref inner type should be unwrapped
  27. const nestedRef = ref({
  28. foo: ref(1)
  29. })
  30. expectType<{ foo: number }>(nestedRef.value)
  31. // ref boolean
  32. const falseRef = ref(false)
  33. expectType<Ref<boolean>>(falseRef)
  34. expectType<boolean>(falseRef.value)
  35. // ref true
  36. const trueRef = ref<true>(true)
  37. expectType<Ref<true>>(trueRef)
  38. expectType<true>(trueRef.value)
  39. // tuple
  40. expectType<[number, string]>(unref(ref([1, '1'])))
  41. interface IteratorFoo {
  42. [Symbol.iterator]: any
  43. }
  44. // with symbol
  45. expectType<Ref<IteratorFoo | null | undefined>>(
  46. ref<IteratorFoo | null | undefined>()
  47. )
  48. // should not unwrap ref inside arrays
  49. const arr = ref([1, new Map<string, any>(), ref('1')]).value
  50. const value = arr[0]
  51. if (isRef(value)) {
  52. expectType<Ref>(value)
  53. } else if (typeof value === 'number') {
  54. expectType<number>(value)
  55. } else {
  56. // should narrow down to Map type
  57. // and not contain any Ref type
  58. expectType<Map<string, any>>(value)
  59. }
  60. // should still unwrap in objects nested in arrays
  61. const arr2 = ref([{ a: ref(1) }]).value
  62. expectType<number>(arr2[0].a)
  63. }
  64. plainType(1)
  65. function bailType(arg: HTMLElement | Ref<HTMLElement>) {
  66. // ref coercing
  67. const coerced = ref(arg)
  68. expectType<Ref<HTMLElement>>(coerced)
  69. // isRef as type guard
  70. if (isRef(arg)) {
  71. expectType<Ref<HTMLElement>>(arg)
  72. }
  73. // ref unwrapping
  74. expectType<HTMLElement>(unref(arg))
  75. // ref inner type should be unwrapped
  76. // eslint-disable-next-line no-restricted-globals
  77. const nestedRef = ref({ foo: ref(document.createElement('DIV')) })
  78. expectType<Ref<{ foo: HTMLElement }>>(nestedRef)
  79. expectType<{ foo: HTMLElement }>(nestedRef.value)
  80. }
  81. // eslint-disable-next-line no-restricted-globals
  82. const el = document.createElement('DIV')
  83. bailType(el)
  84. function withSymbol() {
  85. const customSymbol = Symbol()
  86. const obj = {
  87. [Symbol.asyncIterator]: ref(1),
  88. [Symbol.hasInstance]: { a: ref('a') },
  89. [Symbol.isConcatSpreadable]: { b: ref(true) },
  90. [Symbol.iterator]: [ref(1)],
  91. [Symbol.match]: new Set<Ref<number>>(),
  92. [Symbol.matchAll]: new Map<number, Ref<string>>(),
  93. [Symbol.replace]: { arr: [ref('a')] },
  94. [Symbol.search]: { set: new Set<Ref<number>>() },
  95. [Symbol.species]: { map: new Map<number, Ref<string>>() },
  96. [Symbol.split]: new WeakSet<Ref<boolean>>(),
  97. [Symbol.toPrimitive]: new WeakMap<Ref<boolean>, string>(),
  98. [Symbol.toStringTag]: { weakSet: new WeakSet<Ref<boolean>>() },
  99. [Symbol.unscopables]: { weakMap: new WeakMap<Ref<boolean>, string>() },
  100. [customSymbol]: { arr: [ref(1)] }
  101. }
  102. const objRef = ref(obj)
  103. expectType<Ref<number>>(objRef.value[Symbol.asyncIterator])
  104. expectType<{ a: Ref<string> }>(objRef.value[Symbol.hasInstance])
  105. expectType<{ b: Ref<boolean> }>(objRef.value[Symbol.isConcatSpreadable])
  106. expectType<Ref<number>[]>(objRef.value[Symbol.iterator])
  107. expectType<Set<Ref<number>>>(objRef.value[Symbol.match])
  108. expectType<Map<number, Ref<string>>>(objRef.value[Symbol.matchAll])
  109. expectType<{ arr: Ref<string>[] }>(objRef.value[Symbol.replace])
  110. expectType<{ set: Set<Ref<number>> }>(objRef.value[Symbol.search])
  111. expectType<{ map: Map<number, Ref<string>> }>(objRef.value[Symbol.species])
  112. expectType<WeakSet<Ref<boolean>>>(objRef.value[Symbol.split])
  113. expectType<WeakMap<Ref<boolean>, string>>(objRef.value[Symbol.toPrimitive])
  114. expectType<{ weakSet: WeakSet<Ref<boolean>> }>(
  115. objRef.value[Symbol.toStringTag]
  116. )
  117. expectType<{ weakMap: WeakMap<Ref<boolean>, string> }>(
  118. objRef.value[Symbol.unscopables]
  119. )
  120. expectType<{ arr: Ref<number>[] }>(objRef.value[customSymbol])
  121. }
  122. withSymbol()
  123. const state = reactive({
  124. foo: {
  125. value: 1,
  126. label: 'bar'
  127. }
  128. })
  129. expectType<string>(state.foo.label)
  130. // shallowRef
  131. type Status = 'initial' | 'ready' | 'invalidating'
  132. const shallowStatus = shallowRef<Status>('initial')
  133. if (shallowStatus.value === 'initial') {
  134. expectType<Ref<Status>>(shallowStatus)
  135. expectType<Status>(shallowStatus.value)
  136. shallowStatus.value = 'invalidating'
  137. }
  138. const refStatus = ref<Status>('initial')
  139. if (refStatus.value === 'initial') {
  140. expectType<Ref<Status>>(shallowStatus)
  141. expectType<Status>(shallowStatus.value)
  142. refStatus.value = 'invalidating'
  143. }
  144. // proxyRefs: should return `reactive` directly
  145. const r1 = reactive({
  146. k: 'v'
  147. })
  148. const p1 = proxyRefs(r1)
  149. expectType<typeof r1>(p1)
  150. // proxyRefs: `ShallowUnwrapRef`
  151. const r2 = {
  152. a: ref(1),
  153. obj: {
  154. k: ref('foo')
  155. }
  156. }
  157. const p2 = proxyRefs(r2)
  158. expectType<number>(p2.a)
  159. expectType<Ref<string>>(p2.obj.k)
  160. // toRef
  161. const obj = {
  162. a: 1,
  163. b: ref(1)
  164. }
  165. expectType<Ref<number>>(toRef(obj, 'a'))
  166. expectType<Ref<number>>(toRef(obj, 'b'))
  167. const objWithUnionProp: { a: string | number } = {
  168. a: 1
  169. }
  170. watch(toRef(objWithUnionProp, 'a'), value => {
  171. expectType<string | number>(value)
  172. })
  173. // toRefs
  174. const objRefs = toRefs(obj)
  175. expectType<{
  176. a: Ref<number>
  177. b: Ref<number>
  178. }>(objRefs)
  179. // #2687
  180. interface AppData {
  181. state: 'state1' | 'state2' | 'state3'
  182. }
  183. const data: ToRefs<AppData> = toRefs(
  184. reactive({
  185. state: 'state1'
  186. })
  187. )
  188. switch (data.state.value) {
  189. case 'state1':
  190. data.state.value = 'state2'
  191. break
  192. case 'state2':
  193. data.state.value = 'state3'
  194. break
  195. case 'state3':
  196. data.state.value = 'state1'
  197. break
  198. }
  199. // #3954
  200. function testUnrefGenerics<T>(p: T | Ref<T>) {
  201. expectType<T>(unref(p))
  202. }
  203. testUnrefGenerics(1)
  204. // #4732
  205. const baz = shallowReactive({
  206. foo: {
  207. bar: ref(42)
  208. }
  209. })
  210. const foo = toRef(baz, 'foo')
  211. expectType<Ref<number>>(foo.value.bar)
  212. expectType<number>(foo.value.bar.value)