apiCreateComponent.spec.tsx 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. } as const, // required to narrow for conditional check
  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 a={1} b="foo" dd={['foo']} ddd={['foo']} />
  69. })
  70. test('type inference w/ optional props declaration', () => {
  71. const Comp = createComponent({
  72. setup(props: { msg: string }) {
  73. props.msg
  74. return {
  75. a: 1
  76. }
  77. },
  78. render() {
  79. this.$props.msg
  80. this.msg
  81. this.a * 2
  82. return h('div', this.msg)
  83. }
  84. })
  85. ;<Comp msg="hello" />
  86. })
  87. test('type inference w/ direct setup function', () => {
  88. const Comp = createComponent((props: { msg: string }) => {
  89. return () => <div>{props.msg}</div>
  90. })
  91. ;<Comp msg="hello" />
  92. })
  93. test('type inference w/ array props declaration', () => {
  94. const Comp = createComponent({
  95. props: ['a', 'b'],
  96. setup(props) {
  97. props.a
  98. props.b
  99. return {
  100. c: 1
  101. }
  102. },
  103. render() {
  104. this.$props.a
  105. this.$props.b
  106. this.a
  107. this.b
  108. this.c
  109. }
  110. })
  111. ;<Comp a={1} b={2} />
  112. })
  113. test('with legacy options', () => {
  114. createComponent({
  115. props: { a: Number },
  116. setup() {
  117. return {
  118. b: 123
  119. }
  120. },
  121. data() {
  122. // Limitation: we cannot expose the return result of setup() on `this`
  123. // here in data() - somehow that would mess up the inference
  124. return {
  125. c: this.a || 123
  126. }
  127. },
  128. computed: {
  129. d(): number {
  130. return this.b + 1
  131. }
  132. },
  133. watch: {
  134. a() {
  135. this.b + 1
  136. }
  137. },
  138. created() {
  139. this.a && this.a * 2
  140. this.b * 2
  141. this.c * 2
  142. this.d * 2
  143. },
  144. methods: {
  145. doSomething() {
  146. this.a && this.a * 2
  147. this.b * 2
  148. this.c * 2
  149. this.d * 2
  150. return (this.a || 0) + this.b + this.c + this.d
  151. }
  152. },
  153. render() {
  154. this.a && this.a * 2
  155. this.b * 2
  156. this.c * 2
  157. this.d * 2
  158. return h('div', (this.a || 0) + this.b + this.c + this.d)
  159. }
  160. })
  161. })