defineComponent.test-d.tsx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. import {
  2. describe,
  3. Component,
  4. defineComponent,
  5. PropType,
  6. ref,
  7. reactive,
  8. createApp,
  9. expectError,
  10. expectType,
  11. ComponentPublicInstance,
  12. ComponentOptions,
  13. SetupContext
  14. } from './index'
  15. describe('with object props', () => {
  16. interface ExpectedProps {
  17. a?: number | undefined
  18. b: string
  19. e?: Function
  20. bb: string
  21. bbb: string
  22. cc?: string[] | undefined
  23. dd: { n: 1 }
  24. ee?: () => string
  25. ff?: (a: number, b: string) => { a: boolean }
  26. ccc?: string[] | undefined
  27. ddd: string[]
  28. eee: () => { a: string }
  29. fff: (a: number, b: string) => { a: boolean }
  30. hhh: boolean
  31. ggg: 'foo' | 'bar'
  32. ffff: (a: number, b: string) => { a: boolean }
  33. validated?: string
  34. }
  35. type GT = string & { __brand: unknown }
  36. const MyComponent = defineComponent({
  37. props: {
  38. a: Number,
  39. // required should make property non-void
  40. b: {
  41. type: String,
  42. required: true
  43. },
  44. e: Function,
  45. // default value should infer type and make it non-void
  46. bb: {
  47. default: 'hello'
  48. },
  49. bbb: {
  50. // Note: default function value requires arrow syntax + explicit
  51. // annotation
  52. default: (props: any) => (props.bb as string) || 'foo'
  53. },
  54. // explicit type casting
  55. cc: Array as PropType<string[]>,
  56. // required + type casting
  57. dd: {
  58. type: Object as PropType<{ n: 1 }>,
  59. required: true
  60. },
  61. // return type
  62. ee: Function as PropType<() => string>,
  63. // arguments + object return
  64. ff: Function as PropType<(a: number, b: string) => { a: boolean }>,
  65. // explicit type casting with constructor
  66. ccc: Array as () => string[],
  67. // required + contructor type casting
  68. ddd: {
  69. type: Array as () => string[],
  70. required: true
  71. },
  72. // required + object return
  73. eee: {
  74. type: Function as PropType<() => { a: string }>,
  75. required: true
  76. },
  77. // required + arguments + object return
  78. fff: {
  79. type: Function as PropType<(a: number, b: string) => { a: boolean }>,
  80. required: true
  81. },
  82. hhh: {
  83. type: Boolean,
  84. required: true
  85. },
  86. // default + type casting
  87. ggg: {
  88. type: String as PropType<'foo' | 'bar'>,
  89. default: 'foo'
  90. },
  91. // default + function
  92. ffff: {
  93. type: Function as PropType<(a: number, b: string) => { a: boolean }>,
  94. default: (a: number, b: string) => ({ a: true })
  95. },
  96. validated: {
  97. type: String,
  98. // validator requires explicit annotation
  99. validator: (val: unknown) => val !== ''
  100. }
  101. },
  102. setup(props) {
  103. // type assertion. See https://github.com/SamVerschueren/tsd
  104. expectType<ExpectedProps['a']>(props.a)
  105. expectType<ExpectedProps['b']>(props.b)
  106. expectType<ExpectedProps['e']>(props.e)
  107. expectType<ExpectedProps['bb']>(props.bb)
  108. expectType<ExpectedProps['bbb']>(props.bbb)
  109. expectType<ExpectedProps['cc']>(props.cc)
  110. expectType<ExpectedProps['dd']>(props.dd)
  111. expectType<ExpectedProps['ee']>(props.ee)
  112. expectType<ExpectedProps['ff']>(props.ff)
  113. expectType<ExpectedProps['ccc']>(props.ccc)
  114. expectType<ExpectedProps['ddd']>(props.ddd)
  115. expectType<ExpectedProps['eee']>(props.eee)
  116. expectType<ExpectedProps['fff']>(props.fff)
  117. expectType<ExpectedProps['hhh']>(props.hhh)
  118. expectType<ExpectedProps['ggg']>(props.ggg)
  119. expectType<ExpectedProps['ffff']>(props.ffff)
  120. expectType<ExpectedProps['validated']>(props.validated)
  121. // @ts-expect-error props should be readonly
  122. expectError((props.a = 1))
  123. // setup context
  124. return {
  125. c: ref(1),
  126. d: {
  127. e: ref('hi')
  128. },
  129. f: reactive({
  130. g: ref('hello' as GT)
  131. })
  132. }
  133. },
  134. render() {
  135. const props = this.$props
  136. expectType<ExpectedProps['a']>(props.a)
  137. expectType<ExpectedProps['b']>(props.b)
  138. expectType<ExpectedProps['e']>(props.e)
  139. expectType<ExpectedProps['bb']>(props.bb)
  140. expectType<ExpectedProps['cc']>(props.cc)
  141. expectType<ExpectedProps['dd']>(props.dd)
  142. expectType<ExpectedProps['ee']>(props.ee)
  143. expectType<ExpectedProps['ff']>(props.ff)
  144. expectType<ExpectedProps['ccc']>(props.ccc)
  145. expectType<ExpectedProps['ddd']>(props.ddd)
  146. expectType<ExpectedProps['eee']>(props.eee)
  147. expectType<ExpectedProps['fff']>(props.fff)
  148. expectType<ExpectedProps['hhh']>(props.hhh)
  149. expectType<ExpectedProps['ggg']>(props.ggg)
  150. // @ts-expect-error props should be readonly
  151. expectError((props.a = 1))
  152. // should also expose declared props on `this`
  153. expectType<ExpectedProps['a']>(this.a)
  154. expectType<ExpectedProps['b']>(this.b)
  155. expectType<ExpectedProps['e']>(this.e)
  156. expectType<ExpectedProps['bb']>(this.bb)
  157. expectType<ExpectedProps['cc']>(this.cc)
  158. expectType<ExpectedProps['dd']>(this.dd)
  159. expectType<ExpectedProps['ee']>(this.ee)
  160. expectType<ExpectedProps['ff']>(this.ff)
  161. expectType<ExpectedProps['ccc']>(this.ccc)
  162. expectType<ExpectedProps['ddd']>(this.ddd)
  163. expectType<ExpectedProps['eee']>(this.eee)
  164. expectType<ExpectedProps['fff']>(this.fff)
  165. expectType<ExpectedProps['hhh']>(this.hhh)
  166. expectType<ExpectedProps['ggg']>(this.ggg)
  167. // @ts-expect-error props on `this` should be readonly
  168. expectError((this.a = 1))
  169. // assert setup context unwrapping
  170. expectType<number>(this.c)
  171. expectType<string>(this.d.e.value)
  172. expectType<GT>(this.f.g)
  173. // setup context properties should be mutable
  174. this.c = 2
  175. return null
  176. }
  177. })
  178. expectType<Component>(MyComponent)
  179. // Test TSX
  180. expectType<JSX.Element>(
  181. <MyComponent
  182. a={1}
  183. b="b"
  184. bb="bb"
  185. e={() => {}}
  186. cc={['cc']}
  187. dd={{ n: 1 }}
  188. ee={() => 'ee'}
  189. ccc={['ccc']}
  190. ddd={['ddd']}
  191. eee={() => ({ a: 'eee' })}
  192. fff={(a, b) => ({ a: a > +b })}
  193. hhh={false}
  194. ggg="foo"
  195. // should allow class/style as attrs
  196. class="bar"
  197. style={{ color: 'red' }}
  198. // should allow key
  199. key={'foo'}
  200. // should allow ref
  201. ref={'foo'}
  202. />
  203. )
  204. expectType<Component>(
  205. <MyComponent
  206. b="b"
  207. dd={{ n: 1 }}
  208. ddd={['ddd']}
  209. eee={() => ({ a: 'eee' })}
  210. fff={(a, b) => ({ a: a > +b })}
  211. hhh={false}
  212. />
  213. )
  214. // @ts-expect-error missing required props
  215. expectError(<MyComponent />)
  216. expectError(
  217. // @ts-expect-error wrong prop types
  218. <MyComponent a={'wrong type'} b="foo" dd={{ n: 1 }} ddd={['foo']} />
  219. )
  220. expectError(
  221. // @ts-expect-error wrong prop types
  222. <MyComponent ggg="baz" />
  223. )
  224. // @ts-expect-error
  225. expectError(<MyComponent b="foo" dd={{ n: 'string' }} ddd={['foo']} />)
  226. // `this` should be void inside of prop validators and prop default factories
  227. defineComponent({
  228. props: {
  229. myProp: {
  230. type: Number,
  231. validator(val: unknown): boolean {
  232. // @ts-expect-error
  233. return val !== this.otherProp
  234. },
  235. default(): number {
  236. // @ts-expect-error
  237. return this.otherProp + 1
  238. }
  239. },
  240. otherProp: {
  241. type: Number,
  242. required: true
  243. }
  244. }
  245. })
  246. })
  247. // describe('type inference w/ optional props declaration', () => {
  248. // const MyComponent = defineComponent({
  249. // setup(_props: { msg: string }) {
  250. // return {
  251. // a: 1
  252. // }
  253. // },
  254. // render() {
  255. // expectType<string>(this.$props.msg)
  256. // // props should be readonly
  257. // expectError((this.$props.msg = 'foo'))
  258. // // should not expose on `this`
  259. // expectError(this.msg)
  260. // expectType<number>(this.a)
  261. // return null
  262. // }
  263. // })
  264. // expectType<JSX.Element>(<MyComponent msg="foo" />)
  265. // expectError(<MyComponent />)
  266. // expectError(<MyComponent msg={1} />)
  267. // })
  268. // describe('type inference w/ direct setup function', () => {
  269. // const MyComponent = defineComponent((_props: { msg: string }) => {})
  270. // expectType<JSX.Element>(<MyComponent msg="foo" />)
  271. // expectError(<MyComponent />)
  272. // expectError(<MyComponent msg={1} />)
  273. // })
  274. describe('type inference w/ array props declaration', () => {
  275. const MyComponent = defineComponent({
  276. props: ['a', 'b'],
  277. setup(props) {
  278. // @ts-expect-error props should be readonly
  279. expectError((props.a = 1))
  280. expectType<any>(props.a)
  281. expectType<any>(props.b)
  282. return {
  283. c: 1
  284. }
  285. },
  286. render() {
  287. expectType<any>(this.$props.a)
  288. expectType<any>(this.$props.b)
  289. // @ts-expect-error
  290. expectError((this.$props.a = 1))
  291. expectType<any>(this.a)
  292. expectType<any>(this.b)
  293. expectType<number>(this.c)
  294. }
  295. })
  296. expectType<JSX.Element>(<MyComponent a={[1, 2]} b="b" />)
  297. // @ts-expect-error
  298. expectError(<MyComponent other="other" />)
  299. })
  300. describe('type inference w/ options API', () => {
  301. defineComponent({
  302. props: { a: Number },
  303. setup() {
  304. return {
  305. b: 123
  306. }
  307. },
  308. data() {
  309. // Limitation: we cannot expose the return result of setup() on `this`
  310. // here in data() - somehow that would mess up the inference
  311. expectType<number | undefined>(this.a)
  312. return {
  313. c: this.a || 123
  314. }
  315. },
  316. computed: {
  317. d(): number {
  318. expectType<number>(this.b)
  319. return this.b + 1
  320. },
  321. e: {
  322. get(): number {
  323. expectType<number>(this.b)
  324. expectType<number>(this.d)
  325. return this.b + this.d
  326. },
  327. set(v: number) {
  328. expectType<number>(this.b)
  329. expectType<number>(this.d)
  330. expectType<number>(v)
  331. }
  332. }
  333. },
  334. watch: {
  335. a() {
  336. expectType<number>(this.b)
  337. this.b + 1
  338. }
  339. },
  340. created() {
  341. // props
  342. expectType<number | undefined>(this.a)
  343. // returned from setup()
  344. expectType<number>(this.b)
  345. // returned from data()
  346. expectType<number>(this.c)
  347. // computed
  348. expectType<number>(this.d)
  349. // computed get/set
  350. expectType<number>(this.e)
  351. },
  352. methods: {
  353. doSomething() {
  354. // props
  355. expectType<number | undefined>(this.a)
  356. // returned from setup()
  357. expectType<number>(this.b)
  358. // returned from data()
  359. expectType<number>(this.c)
  360. // computed
  361. expectType<number>(this.d)
  362. // computed get/set
  363. expectType<number>(this.e)
  364. },
  365. returnSomething() {
  366. return this.a
  367. }
  368. },
  369. render() {
  370. // props
  371. expectType<number | undefined>(this.a)
  372. // returned from setup()
  373. expectType<number>(this.b)
  374. // returned from data()
  375. expectType<number>(this.c)
  376. // computed
  377. expectType<number>(this.d)
  378. // computed get/set
  379. expectType<number>(this.e)
  380. // method
  381. expectType<() => number | undefined>(this.returnSomething)
  382. }
  383. })
  384. })
  385. describe('with mixins', () => {
  386. const MixinA = defineComponent({
  387. props: {
  388. aP1: {
  389. type: String,
  390. default: 'aP1'
  391. },
  392. aP2: Boolean
  393. },
  394. data() {
  395. return {
  396. a: 1
  397. }
  398. }
  399. })
  400. const MixinB = defineComponent({
  401. props: ['bP1', 'bP2'],
  402. data() {
  403. return {
  404. b: 2
  405. }
  406. }
  407. })
  408. const MixinC = defineComponent({
  409. data() {
  410. return {
  411. c: 3
  412. }
  413. }
  414. })
  415. const MixinD = defineComponent({
  416. mixins: [MixinA],
  417. data() {
  418. return {
  419. d: 4
  420. }
  421. },
  422. computed: {
  423. dC1(): number {
  424. return this.d + this.a
  425. },
  426. dC2(): string {
  427. return this.aP1 + 'dC2'
  428. }
  429. }
  430. })
  431. const MyComponent = defineComponent({
  432. mixins: [MixinA, MixinB, MixinC, MixinD],
  433. props: {
  434. // required should make property non-void
  435. z: {
  436. type: String,
  437. required: true
  438. }
  439. },
  440. render() {
  441. const props = this.$props
  442. // props
  443. expectType<string>(props.aP1)
  444. expectType<boolean | undefined>(props.aP2)
  445. expectType<any>(props.bP1)
  446. expectType<any>(props.bP2)
  447. expectType<string>(props.z)
  448. const data = this.$data
  449. expectType<number>(data.a)
  450. expectType<number>(data.b)
  451. expectType<number>(data.c)
  452. expectType<number>(data.d)
  453. // should also expose declared props on `this`
  454. expectType<number>(this.a)
  455. expectType<string>(this.aP1)
  456. expectType<boolean | undefined>(this.aP2)
  457. expectType<number>(this.b)
  458. expectType<any>(this.bP1)
  459. expectType<number>(this.c)
  460. expectType<number>(this.d)
  461. expectType<number>(this.dC1)
  462. expectType<string>(this.dC2)
  463. // props should be readonly
  464. // @ts-expect-error
  465. expectError((this.aP1 = 'new'))
  466. // @ts-expect-error
  467. expectError((this.z = 1))
  468. // props on `this` should be readonly
  469. // @ts-expect-error
  470. expectError((this.bP1 = 1))
  471. // string value can not assigned to number type value
  472. // @ts-expect-error
  473. expectError((this.c = '1'))
  474. // setup context properties should be mutable
  475. this.d = 5
  476. return null
  477. }
  478. })
  479. // Test TSX
  480. expectType<JSX.Element>(
  481. <MyComponent aP1={'aP'} aP2 bP1={1} bP2={[1, 2]} z={'z'} />
  482. )
  483. // missing required props
  484. // @ts-expect-error
  485. expectError(<MyComponent />)
  486. // wrong prop types
  487. // @ts-expect-error
  488. expectError(<MyComponent aP1="ap" aP2={'wrong type'} bP1="b" z={'z'} />)
  489. // @ts-expect-error
  490. expectError(<MyComponent aP1={1} bP2={[1]} />)
  491. })
  492. describe('with extends', () => {
  493. const Base = defineComponent({
  494. props: {
  495. aP1: Boolean,
  496. aP2: {
  497. type: Number,
  498. default: 2
  499. }
  500. },
  501. data() {
  502. return {
  503. a: 1
  504. }
  505. },
  506. computed: {
  507. c(): number {
  508. return this.aP2 + this.a
  509. }
  510. }
  511. })
  512. const MyComponent = defineComponent({
  513. extends: Base,
  514. props: {
  515. // required should make property non-void
  516. z: {
  517. type: String,
  518. required: true
  519. }
  520. },
  521. render() {
  522. const props = this.$props
  523. // props
  524. expectType<boolean | undefined>(props.aP1)
  525. expectType<number>(props.aP2)
  526. expectType<string>(props.z)
  527. const data = this.$data
  528. expectType<number>(data.a)
  529. // should also expose declared props on `this`
  530. expectType<number>(this.a)
  531. expectType<boolean | undefined>(this.aP1)
  532. expectType<number>(this.aP2)
  533. // setup context properties should be mutable
  534. this.a = 5
  535. return null
  536. }
  537. })
  538. // Test TSX
  539. expectType<JSX.Element>(<MyComponent aP2={3} aP1 z={'z'} />)
  540. // missing required props
  541. // @ts-expect-error
  542. expectError(<MyComponent />)
  543. // wrong prop types
  544. // @ts-expect-error
  545. expectError(<MyComponent aP2={'wrong type'} z={'z'} />)
  546. // @ts-expect-error
  547. expectError(<MyComponent aP1={3} />)
  548. })
  549. describe('extends with mixins', () => {
  550. const Mixin = defineComponent({
  551. props: {
  552. mP1: {
  553. type: String,
  554. default: 'mP1'
  555. },
  556. mP2: Boolean
  557. },
  558. data() {
  559. return {
  560. a: 1
  561. }
  562. }
  563. })
  564. const Base = defineComponent({
  565. props: {
  566. p1: Boolean,
  567. p2: {
  568. type: Number,
  569. default: 2
  570. }
  571. },
  572. data() {
  573. return {
  574. b: 2
  575. }
  576. },
  577. computed: {
  578. c(): number {
  579. return this.p2 + this.b
  580. }
  581. }
  582. })
  583. const MyComponent = defineComponent({
  584. extends: Base,
  585. mixins: [Mixin],
  586. props: {
  587. // required should make property non-void
  588. z: {
  589. type: String,
  590. required: true
  591. }
  592. },
  593. render() {
  594. const props = this.$props
  595. // props
  596. expectType<boolean | undefined>(props.p1)
  597. expectType<number>(props.p2)
  598. expectType<string>(props.z)
  599. expectType<string>(props.mP1)
  600. expectType<boolean | undefined>(props.mP2)
  601. const data = this.$data
  602. expectType<number>(data.a)
  603. expectType<number>(data.b)
  604. // should also expose declared props on `this`
  605. expectType<number>(this.a)
  606. expectType<number>(this.b)
  607. expectType<boolean | undefined>(this.p1)
  608. expectType<number>(this.p2)
  609. expectType<string>(this.mP1)
  610. expectType<boolean | undefined>(this.mP2)
  611. // setup context properties should be mutable
  612. this.a = 5
  613. return null
  614. }
  615. })
  616. // Test TSX
  617. expectType<JSX.Element>(<MyComponent mP1="p1" mP2 p1 p2={1} z={'z'} />)
  618. // missing required props
  619. // @ts-expect-error
  620. expectError(<MyComponent />)
  621. // wrong prop types
  622. // @ts-expect-error
  623. expectError(<MyComponent p2={'wrong type'} z={'z'} />)
  624. // @ts-expect-error
  625. expectError(<MyComponent mP1={3} />)
  626. })
  627. describe('compatibility w/ createApp', () => {
  628. const comp = defineComponent({})
  629. createApp(comp).mount('#hello')
  630. const comp2 = defineComponent({
  631. props: { foo: String }
  632. })
  633. createApp(comp2).mount('#hello')
  634. const comp3 = defineComponent({
  635. setup() {
  636. return {
  637. a: 1
  638. }
  639. }
  640. })
  641. createApp(comp3).mount('#hello')
  642. })
  643. describe('defineComponent', () => {
  644. test('should accept components defined with defineComponent', () => {
  645. const comp = defineComponent({})
  646. defineComponent({
  647. components: { comp }
  648. })
  649. })
  650. })
  651. describe('emits', () => {
  652. // Note: for TSX inference, ideally we want to map emits to onXXX props,
  653. // but that requires type-level string constant concatenation as suggested in
  654. // https://github.com/Microsoft/TypeScript/issues/12754
  655. // The workaround for TSX users is instead of using emits, declare onXXX props
  656. // and call them instead. Since `v-on:click` compiles to an `onClick` prop,
  657. // this would also support other users consuming the component in templates
  658. // with `v-on` listeners.
  659. // with object emits
  660. defineComponent({
  661. emits: {
  662. click: (n: number) => typeof n === 'number',
  663. input: (b: string) => b.length > 1
  664. },
  665. setup(props, { emit }) {
  666. emit('click', 1)
  667. emit('input', 'foo')
  668. // @ts-expect-error
  669. expectError(emit('nope'))
  670. // @ts-expect-error
  671. expectError(emit('click'))
  672. // @ts-expect-error
  673. expectError(emit('click', 'foo'))
  674. // @ts-expect-error
  675. expectError(emit('input'))
  676. // @ts-expect-error
  677. expectError(emit('input', 1))
  678. },
  679. created() {
  680. this.$emit('click', 1)
  681. this.$emit('input', 'foo')
  682. // @ts-expect-error
  683. expectError(this.$emit('nope'))
  684. // @ts-expect-error
  685. expectError(this.$emit('click'))
  686. // @ts-expect-error
  687. expectError(this.$emit('click', 'foo'))
  688. // @ts-expect-error
  689. expectError(this.$emit('input'))
  690. // @ts-expect-error
  691. expectError(this.$emit('input', 1))
  692. }
  693. })
  694. // with array emits
  695. defineComponent({
  696. emits: ['foo', 'bar'],
  697. setup(props, { emit }) {
  698. emit('foo')
  699. emit('foo', 123)
  700. emit('bar')
  701. // @ts-expect-error
  702. expectError(emit('nope'))
  703. },
  704. created() {
  705. this.$emit('foo')
  706. this.$emit('foo', 123)
  707. this.$emit('bar')
  708. // @ts-expect-error
  709. expectError(this.$emit('nope'))
  710. }
  711. })
  712. // without emits
  713. defineComponent({
  714. setup(props, { emit }) {
  715. emit('test', 1)
  716. emit('test')
  717. }
  718. })
  719. // emit should be valid when ComponentPublicInstance is used.
  720. const instance = {} as ComponentPublicInstance
  721. instance.$emit('test', 1)
  722. instance.$emit('test')
  723. // `this` should be void inside of emits validators
  724. defineComponent({
  725. props: ['bar'],
  726. emits: {
  727. foo(): boolean {
  728. // @ts-expect-error
  729. return this.bar === 3
  730. }
  731. }
  732. })
  733. })
  734. describe('componentOptions setup should be `SetupContext`', () => {
  735. expect<ComponentOptions['setup']>({} as (
  736. props: Record<string, any>,
  737. ctx: SetupContext
  738. ) => any)
  739. })