h.test-d.ts 6.0 KB

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