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

Conditional properties through discriminated unions and intersections in TypeScript #8952

Open
theguriev opened this issue Aug 10, 2023 · 9 comments
Labels
🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. scope: script-setup scope: types

Comments

@theguriev
Copy link

What problem does this feature solve?

#7553
Reopening this because I believe the problem is not solved. It is still impossible to use coditional props.

Just try this after npm create vue@latest inside HelloWorld component

<script setup lang="ts">
interface CommonProps {
  size?: 'xl' | 'l' | 'm' | 's' | 'xs'
}

type ConditionalProps =
  | {
      color?: 'normal' | 'primary' | 'secondary'
      appearance?: 'normal' | 'outline' | 'text'
    }
  | {
      color: 'white'
      appearance: 'outline'
    }

type Props = CommonProps & ConditionalProps
defineProps<Props>()
</script>

and then try to use it

image

Theoretically it should not allow us to use both. That is, there can't be color="white" appearance="text" only color="white" appearance="outline"

What does the proposed API look like?

{
      color?: 'normal' | 'primary' | 'secondary'
      appearance?: 'normal' | 'outline' | 'text'
    }
  | {
      color: 'white'
      appearance: 'outline'
    }
@theguriev theguriev added the ✨ feature request New feature or request label Aug 10, 2023
@manniL
Copy link

manniL commented Aug 10, 2023

Added another simple example with fully "exclusive" props that should be covered as well and does not work (yet).

@goulashify
Copy link

I ran into this many times, huge +1.

@DaniilIsupov
Copy link

Typescript allows me to use Conditional Types, but Vue doesn't allow me to do this

@louiss0
Copy link

louiss0 commented Nov 3, 2023

C'mon Vue and TS NEED FULL SYNERGY.

@sxzz sxzz added 🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. scope: types and removed ✨ feature request New feature or request scope: compiler labels Nov 4, 2023
@ThejanNim
Copy link

ThejanNim commented Feb 28, 2024

Hi guys, Any update here? @sxzz if you can please follow up on this issue.

@johnsoncodehk
Copy link
Member

This is a type restriction of defineComponent, as a current solution you can use generic. This will bypass defineComponent and define the component as a functional component.

<script setup lang="ts" generic="T">
interface CommonProps {
  size?: 'xl' | 'l' | 'm' | 's' | 'xs'
}
// ...
</script>

@occitaneUbald
Copy link

This is a type restriction of defineComponent, as a current solution you can use generic. This will bypass defineComponent and define the component as a functional component.

<script setup lang="ts" generic="T">
interface CommonProps {
  size?: 'xl' | 'l' | 'm' | 's' | 'xs'
}
// ...
</script>

Unfortunately vue-test-utils does not support generic components with Typescript

@manniL
Copy link

manniL commented May 31, 2024

This is a type restriction of defineComponent, as a current solution you can use generic. This will bypass defineComponent and define the component as a functional component.

<script setup lang="ts" generic="T">
interface CommonProps {
  size?: 'xl' | 'l' | 'm' | 's' | 'xs'
}
// ...
</script>

@johnsoncodehk while props with a discriminator work now in the playground (e.g. color in the example above), two different props as in my comment are still not possible as far as I see.

@AdrianFahrbach
Copy link

Any updates on the plans for this?
I guess with recent PR #10801 this is in the works?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍰 p2-nice-to-have Priority 2: this is not breaking anything but nice to have it addressed. scope: script-setup scope: types
Projects
None yet
Development

No branches or pull requests