ref.test-d.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  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. watch
  14. } from './index'
  15. function plainType(arg: number | Ref<number>) {
  16. // ref coercing
  17. const coerced = ref(arg)
  18. expectType<Ref<number>>(coerced)
  19. // isRef as type guard
  20. if (isRef(arg)) {
  21. expectType<Ref<number>>(arg)
  22. }
  23. // ref unwrapping
  24. expectType<number>(unref(arg))
  25. // ref inner type should be unwrapped
  26. const nestedRef = ref({
  27. foo: ref(1)
  28. })
  29. expectType<{ foo: number }>(nestedRef.value)
  30. // ref boolean
  31. const falseRef = ref(false)
  32. expectType<Ref<boolean>>(falseRef)
  33. expectType<boolean>(falseRef.value)
  34. // ref true
  35. const trueRef = ref<true>(true)
  36. expectType<Ref<true>>(trueRef)
  37. expectType<true>(trueRef.value)
  38. // tuple
  39. expectType<[number, string]>(unref(ref([1, '1'])))
  40. interface IteratorFoo {
  41. [Symbol.iterator]: any
  42. }
  43. // with symbol
  44. expectType<Ref<IteratorFoo | null | undefined>>(
  45. ref<IteratorFoo | null | undefined>()
  46. )
  47. // should not unwrap ref inside arrays
  48. const arr = ref([1, new Map<string, any>(), ref('1')]).value
  49. const value = arr[0]
  50. if (isRef(value)) {
  51. expectType<Ref>(value)
  52. } else if (typeof value === 'number') {
  53. expectType<number>(value)
  54. } else {
  55. // should narrow down to Map type
  56. // and not contain any Ref type
  57. expectType<Map<string, any>>(value)
  58. }
  59. // should still unwrap in objects nested in arrays
  60. const arr2 = ref([{ a: ref(1) }]).value
  61. expectType<number>(arr2[0].a)
  62. }
  63. plainType(1)
  64. function bailType(arg: HTMLElement | Ref<HTMLElement>) {
  65. // ref coercing
  66. const coerced = ref(arg)
  67. expectType<Ref<HTMLElement>>(coerced)
  68. // isRef as type guard
  69. if (isRef(arg)) {
  70. expectType<Ref<HTMLElement>>(arg)
  71. }
  72. // ref unwrapping
  73. expectType<HTMLElement>(unref(arg))
  74. // ref inner type should be unwrapped
  75. // eslint-disable-next-line no-restricted-globals
  76. const nestedRef = ref({ foo: ref(document.createElement('DIV')) })
  77. expectType<Ref<{ foo: HTMLElement }>>(nestedRef)
  78. expectType<{ foo: HTMLElement }>(nestedRef.value)
  79. }
  80. // eslint-disable-next-line no-restricted-globals
  81. const el = document.createElement('DIV')
  82. bailType(el)
  83. function withSymbol() {
  84. const customSymbol = Symbol()
  85. const obj = {
  86. [Symbol.asyncIterator]: { a: 1 },
  87. [Symbol.unscopables]: { b: '1' },
  88. [customSymbol]: { c: [1, 2, 3] }
  89. }
  90. const objRef = ref(obj)
  91. expectType<{ a: number }>(objRef.value[Symbol.asyncIterator])
  92. expectType<{ b: string }>(objRef.value[Symbol.unscopables])
  93. expectType<{ c: Array<number> }>(objRef.value[customSymbol])
  94. }
  95. withSymbol()
  96. const state = reactive({
  97. foo: {
  98. value: 1,
  99. label: 'bar'
  100. }
  101. })
  102. expectType<string>(state.foo.label)
  103. // shallowRef
  104. type Status = 'initial' | 'ready' | 'invalidating'
  105. const shallowStatus = shallowRef<Status>('initial')
  106. if (shallowStatus.value === 'initial') {
  107. expectType<Ref<Status>>(shallowStatus)
  108. expectType<Status>(shallowStatus.value)
  109. shallowStatus.value = 'invalidating'
  110. }
  111. const refStatus = ref<Status>('initial')
  112. if (refStatus.value === 'initial') {
  113. expectType<Ref<Status>>(shallowStatus)
  114. expectType<Status>(shallowStatus.value)
  115. refStatus.value = 'invalidating'
  116. }
  117. // proxyRefs: should return `reactive` directly
  118. const r1 = reactive({
  119. k: 'v'
  120. })
  121. const p1 = proxyRefs(r1)
  122. expectType<typeof r1>(p1)
  123. // proxyRefs: `ShallowUnwrapRef`
  124. const r2 = {
  125. a: ref(1),
  126. obj: {
  127. k: ref('foo')
  128. }
  129. }
  130. const p2 = proxyRefs(r2)
  131. expectType<number>(p2.a)
  132. expectType<Ref<string>>(p2.obj.k)
  133. // toRef
  134. const obj = {
  135. a: 1,
  136. b: ref(1)
  137. }
  138. expectType<Ref<number>>(toRef(obj, 'a'))
  139. expectType<Ref<number>>(toRef(obj, 'b'))
  140. const objWithUnionProp: { a: string | number } = {
  141. a: 1
  142. }
  143. watch(toRef(objWithUnionProp, 'a'), value => {
  144. expectType<string | number>(value)
  145. })
  146. // toRefs
  147. const objRefs = toRefs(obj)
  148. expectType<{
  149. a: Ref<number>
  150. b: Ref<number>
  151. }>(objRefs)
  152. // #2687
  153. interface AppData {
  154. state: 'state1' | 'state2' | 'state3'
  155. }
  156. const data: ToRefs<AppData> = toRefs(
  157. reactive({
  158. state: 'state1'
  159. })
  160. )
  161. switch (data.state.value) {
  162. case 'state1':
  163. data.state.value = 'state2'
  164. break
  165. case 'state2':
  166. data.state.value = 'state3'
  167. break
  168. case 'state3':
  169. data.state.value = 'state1'
  170. break
  171. }