h.test-d.ts 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. import {
  2. type Component,
  3. type DefineComponent,
  4. Fragment,
  5. Suspense,
  6. Teleport,
  7. defineComponent,
  8. h,
  9. ref,
  10. resolveComponent,
  11. } from 'vue'
  12. import { describe, expectAssignable, expectType } from './utils'
  13. describe('h inference w/ element', () => {
  14. // key
  15. h('div', { key: 1 })
  16. h('div', { key: 'foo' })
  17. // @ts-expect-error
  18. h('div', { key: [] })
  19. // @ts-expect-error
  20. h('div', { key: {} })
  21. // ref
  22. h('div', { ref: 'foo' })
  23. h('div', { ref: ref(null) })
  24. h('div', { ref: _el => {} })
  25. // @ts-expect-error
  26. h('div', { ref: [] })
  27. // @ts-expect-error
  28. h('div', { ref: {} })
  29. // @ts-expect-error
  30. h('div', { ref: 123 })
  31. // slots
  32. const slots = { default: () => {} } // RawSlots
  33. h('div', {}, slots)
  34. // events
  35. h('div', {
  36. onClick: e => {
  37. expectType<MouseEvent>(e)
  38. },
  39. })
  40. h('input', {
  41. onFocus(e) {
  42. expectType<FocusEvent>(e)
  43. },
  44. })
  45. })
  46. describe('h inference w/ Fragment', () => {
  47. // only accepts array children
  48. h(Fragment, ['hello'])
  49. h(Fragment, { key: 123 }, ['hello'])
  50. // @ts-expect-error
  51. h(Fragment, 'foo')
  52. // @ts-expect-error
  53. h(Fragment, { key: 123 }, 'bar')
  54. })
  55. describe('h inference w/ Teleport', () => {
  56. h(Teleport, { to: '#foo' }, 'hello')
  57. h(Teleport, { to: '#foo' }, { default() {} })
  58. // @ts-expect-error
  59. h(Teleport)
  60. // @ts-expect-error
  61. h(Teleport, {})
  62. // @ts-expect-error
  63. h(Teleport, { to: '#foo' })
  64. })
  65. describe('h inference w/ Suspense', () => {
  66. h(Suspense, { onRecede: () => {}, onResolve: () => {} }, 'hello')
  67. h(Suspense, 'foo')
  68. h(Suspense, () => 'foo')
  69. h(Suspense, null, {
  70. default: () => 'foo',
  71. })
  72. // @ts-expect-error
  73. h(Suspense, { onResolve: 1 })
  74. })
  75. describe('h inference w/ functional component', () => {
  76. const Func = (_props: { foo: string; bar?: number }) => ''
  77. h(Func, { foo: 'hello' })
  78. h(Func, { foo: 'hello', bar: 123 })
  79. // @ts-expect-error
  80. h(Func, { foo: 123 })
  81. // @ts-expect-error
  82. h(Func, {})
  83. // @ts-expect-error
  84. h(Func, { bar: 123 })
  85. })
  86. describe('h support w/ plain object component', () => {
  87. const Foo = {
  88. props: {
  89. foo: String,
  90. },
  91. }
  92. h(Foo, { foo: 'ok' })
  93. h(Foo, { foo: 'ok', class: 'extra' })
  94. // no inference in this case
  95. })
  96. describe('h inference w/ defineComponent', () => {
  97. const Foo = defineComponent({
  98. props: {
  99. foo: String,
  100. bar: {
  101. type: Number,
  102. required: true,
  103. },
  104. },
  105. })
  106. h(Foo, { bar: 1 })
  107. h(Foo, { bar: 1, foo: 'ok' })
  108. // should allow extraneous props (attrs fallthrough)
  109. h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
  110. // @ts-expect-error should fail on missing required prop
  111. h(Foo, {})
  112. // @ts-expect-error
  113. h(Foo, { foo: 'ok' })
  114. // @ts-expect-error should fail on wrong type
  115. h(Foo, { bar: 1, foo: 1 })
  116. })
  117. // describe('h inference w/ defineComponent + optional props', () => {
  118. // const Foo = defineComponent({
  119. // setup(_props: { foo?: string; bar: number }) {}
  120. // })
  121. // h(Foo, { bar: 1 })
  122. // h(Foo, { bar: 1, foo: 'ok' })
  123. // // should allow extraneous props (attrs fallthrough)
  124. // h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
  125. // // @ts-expect-error should fail on missing required prop
  126. // h(Foo, {})
  127. // // @ts-expect-error
  128. // h(Foo, { foo: 'ok' })
  129. // // @ts-expect-error should fail on wrong type
  130. // h(Foo, { bar: 1, foo: 1 })
  131. // })
  132. // describe('h inference w/ defineComponent + direct function', () => {
  133. // const Foo = defineComponent((_props: { foo?: string; bar: number }) => {})
  134. // h(Foo, { bar: 1 })
  135. // h(Foo, { bar: 1, foo: 'ok' })
  136. // // should allow extraneous props (attrs fallthrough)
  137. // h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
  138. // // @ts-expect-error should fail on missing required prop
  139. // h(Foo, {})
  140. // // @ts-expect-error
  141. // h(Foo, { foo: 'ok' })
  142. // // @ts-expect-error should fail on wrong type
  143. // h(Foo, { bar: 1, foo: 1 })
  144. // })
  145. // #922 and #3218
  146. describe('h support for generic component type', () => {
  147. function foo(bar: Component) {
  148. h(bar)
  149. h(bar, 'hello')
  150. h(bar, { id: 'ok' }, 'hello')
  151. }
  152. foo({})
  153. })
  154. // #993
  155. describe('describeComponent extends Component', () => {
  156. // functional
  157. expectAssignable<Component>(
  158. defineComponent((_props: { foo?: string; bar: number }) => () => {}),
  159. )
  160. // typed props
  161. expectAssignable<Component>(defineComponent({}))
  162. // prop arrays
  163. expectAssignable<Component>(
  164. defineComponent({
  165. props: ['a', 'b'],
  166. }),
  167. )
  168. // prop object
  169. expectAssignable<Component>(
  170. defineComponent({
  171. props: {
  172. foo: String,
  173. bar: {
  174. type: Number,
  175. required: true,
  176. },
  177. },
  178. }),
  179. )
  180. })
  181. // #1385
  182. describe('component w/ props w/ default value', () => {
  183. const MyComponent = defineComponent({
  184. props: {
  185. message: {
  186. type: String,
  187. default: 'hello',
  188. },
  189. },
  190. })
  191. h(MyComponent, {})
  192. })
  193. // #2338
  194. describe('Boolean prop implicit false', () => {
  195. const MyComponent = defineComponent({
  196. props: {
  197. visible: Boolean,
  198. },
  199. })
  200. h(MyComponent, {})
  201. const RequiredComponent = defineComponent({
  202. props: {
  203. visible: {
  204. type: Boolean,
  205. required: true,
  206. },
  207. },
  208. })
  209. h(RequiredComponent, {
  210. visible: true,
  211. })
  212. // @ts-expect-error
  213. h(RequiredComponent, {})
  214. })
  215. // #2357
  216. describe('resolveComponent should work', () => {
  217. h(resolveComponent('test'))
  218. h(resolveComponent('test'), {
  219. message: '1',
  220. })
  221. })
  222. // #5431
  223. describe('h should work with multiple types', () => {
  224. const serializers = {
  225. Paragraph: 'p',
  226. Component: {} as Component,
  227. DefineComponent: {} as DefineComponent,
  228. }
  229. const sampleComponent = serializers['' as keyof typeof serializers]
  230. h(sampleComponent)
  231. h(sampleComponent, {})
  232. h(sampleComponent, {}, [])
  233. })