Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for using discriminated union props with defineComponent and runtime props #8591

Closed
justin-schroeder opened this issue Jun 16, 2023 · 1 comment

Comments

@justin-schroeder
Copy link

Vue version

3.3.4

Link to minimal reproduction

https://github.com/justin-schroeder/vue-3.3-prop-unions

Steps to reproduce

Clone the repository and install:

git clone git@github.com:justin-schroeder/vue-3.3-prop-unions.git
cd vue-3.3-prop-unions.git
pnpm install
pnpm build

What is expected?

There are 2 ideas to highlight here:

TypeScript

The example defines a component using the new function syntax for defineComponent with a discriminated union as the prop type. Each union type has 1 prop the other type does not have (bar vs foo). The runtime props include both bar and foo to ensure they are both accepted at runtime.

import { defineComponent, h } from "vue"
import type { RenderFunction } from "vue"

type Pizza = { type: "pizza"; toppings: "pepperoni" | "pineapple"; bar: string }
type Pie = { type: "pie"; toppings: "apple" | "cherry"; foo: string }
type PropUnion = Pizza | Pie

export default defineComponent(
  function setup<P extends PropUnion>(props: P): RenderFunction {
    return () => h("div", `${props.type} with ${props.toppings}`)
  },
  {
    props: ["type", "toppings", "foo", "bar"],
  }
)

I would expect this to work properly since the runtime props are inclusive of all unions, there is no overload that allows for the runtime props to differ from the union props even if the runtime props are only defining additional props. Volar is actually ok with this typing, but Vue itself does not have a matching component overload. For example:

image

Adding an additional overload for defineComponent seems like it may sufficiently address this.

Runtime prop proposal

Alternatively, it would be ideal to allow for runtime props to be determined at runtime. This seems like it would be primary beneficial to library authors, so perhaps no SFC compatibility is necessary. One option:

// Signature:
DefineComponent<P, E...>(setup<P>(props: P, context: SetupContext<E, S>): RenderFunction, options?: Omit<ComponentOptions, 'props'> & { props: (allAttrs: Record<string, any>): P }): (props: P & EmitsToProps<E>) => any

defineComponent(
  function setup<P>(props: P) {
   //...
  },
 {
   props (allAttrs: Record<string, any>): P /* <-- actual runtime props */  {
    if (allAttrs.type === 'foo') {
      return ['a', 'b', 'c']
    }
    return ['d', 'e', 'f']
   }
 }
)

What is actually happening?

No overload matches this call

image

System Info

System:
    OS: macOS 13.1
    CPU: (10) arm64 Apple M1 Pro
    Memory: 84.44 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.14.2 - /usr/local/bin/node
    Yarn: 1.22.18 - ~/.yarn/bin/yarn
    npm: 9.5.0 - /usr/local/bin/npm
  Browsers:
    Brave Browser: 114.1.52.126
    Chrome: 114.0.5735.133
    Edge: 114.0.1823.51
    Firefox: 111.0.1
    Safari: 16.2
  npmPackages:
    vue: ^3.3.4 => 3.3.4

Any additional comments?

No response

@pikax
Copy link
Member

pikax commented Nov 3, 2023

duplicate of #9335

Closing this one, because the other one has a PR attached.

@pikax pikax closed this as completed Nov 3, 2023
@github-actions github-actions bot locked and limited conversation to collaborators Nov 18, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants