apiCreateComponent.spec.tsx 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import { createComponent } from '../src/apiCreateComponent'
  2. import { ref } from '@vue/reactivity'
  3. import { PropType } from '../src/componentProps'
  4. import { h } from '../src/h'
  5. // mock React just for TSX testing purposes
  6. const React = {
  7. createElement: () => {}
  8. }
  9. test('createComponent type inference', () => {
  10. const MyComponent = createComponent({
  11. props: {
  12. a: Number,
  13. // required should make property non-void
  14. b: {
  15. type: String,
  16. required: true
  17. },
  18. // default value should infer type and make it non-void
  19. bb: {
  20. default: 'hello'
  21. },
  22. // explicit type casting
  23. cc: Array as PropType<string[]>,
  24. // required + type casting
  25. dd: {
  26. type: Array as PropType<string[]>,
  27. required: true
  28. },
  29. // explicit type casting with constructor
  30. ccc: Array as () => string[],
  31. // required + contructor type casting
  32. ddd: {
  33. type: Array as () => string[],
  34. required: true
  35. }
  36. },
  37. setup(props) {
  38. props.a && props.a * 2
  39. props.b.slice()
  40. props.bb.slice()
  41. props.cc && props.cc.push('hoo')
  42. props.dd.push('dd')
  43. return {
  44. c: ref(1),
  45. d: {
  46. e: ref('hi')
  47. }
  48. }
  49. },
  50. render() {
  51. const props = this.$props
  52. props.a && props.a * 2
  53. props.b.slice()
  54. props.bb.slice()
  55. props.cc && props.cc.push('hoo')
  56. props.dd.push('dd')
  57. this.a && this.a * 2
  58. this.b.slice()
  59. this.bb.slice()
  60. this.c * 2
  61. this.d.e.slice()
  62. this.cc && this.cc.push('hoo')
  63. this.dd.push('dd')
  64. return h('div', this.bb)
  65. }
  66. })
  67. // test TSX props inference
  68. ;<MyComponent
  69. a={1}
  70. b="foo"
  71. dd={['foo']}
  72. ddd={['foo']}
  73. // should allow extraneous as attrs
  74. class="bar"
  75. />
  76. })
  77. test('type inference w/ optional props declaration', () => {
  78. const Comp = createComponent({
  79. setup(props: { msg: string }) {
  80. props.msg
  81. return {
  82. a: 1
  83. }
  84. },
  85. render() {
  86. this.$props.msg
  87. this.msg
  88. this.a * 2
  89. return h('div', this.msg)
  90. }
  91. })
  92. ;<Comp msg="hello" />
  93. })
  94. test('type inference w/ direct setup function', () => {
  95. const Comp = createComponent((props: { msg: string }) => {
  96. return () => <div>{props.msg}</div>
  97. })
  98. ;<Comp msg="hello" />
  99. })
  100. test('type inference w/ array props declaration', () => {
  101. const Comp = createComponent({
  102. props: ['a', 'b'],
  103. setup(props) {
  104. props.a
  105. props.b
  106. return {
  107. c: 1
  108. }
  109. },
  110. render() {
  111. this.$props.a
  112. this.$props.b
  113. this.a
  114. this.b
  115. this.c
  116. }
  117. })
  118. ;<Comp a={1} b={2} />
  119. })
  120. test('with legacy options', () => {
  121. createComponent({
  122. props: { a: Number },
  123. setup() {
  124. return {
  125. b: 123
  126. }
  127. },
  128. data() {
  129. // Limitation: we cannot expose the return result of setup() on `this`
  130. // here in data() - somehow that would mess up the inference
  131. return {
  132. c: this.a || 123
  133. }
  134. },
  135. computed: {
  136. d(): number {
  137. return this.b + 1
  138. }
  139. },
  140. watch: {
  141. a() {
  142. this.b + 1
  143. }
  144. },
  145. created() {
  146. this.a && this.a * 2
  147. this.b * 2
  148. this.c * 2
  149. this.d * 2
  150. },
  151. methods: {
  152. doSomething() {
  153. this.a && this.a * 2
  154. this.b * 2
  155. this.c * 2
  156. this.d * 2
  157. return (this.a || 0) + this.b + this.c + this.d
  158. }
  159. },
  160. render() {
  161. this.a && this.a * 2
  162. this.b * 2
  163. this.c * 2
  164. this.d * 2
  165. return h('div', (this.a || 0) + this.b + this.c + this.d)
  166. }
  167. })
  168. })