core icon indicating copy to clipboard operation
core copied to clipboard

feat: runtime-support for type unions in props

Open davidmatter opened this issue 4 months ago • 11 comments

One of the last missing features regarding TypeScript support in Vue is the ability to use discriminated- and distributive union types in props with runtime validation. This PR aims to address these limitations and provides a more flexible way to define props.

Fixes

  • https://github.com/vuejs/core/issues/11758
  • https://github.com/vuejs/core/issues/8952
  • https://github.com/vuejs/core/issues/9125
  • https://github.com/vuejs/core/issues/12106

Implementation

Through compiling and validating the new internal prop option union, we can skip validation for props that are not part of an active sub-union.

In the following example, a and b are in an active sub-union, c and d are not. Defining either a or b should trigger warnings for missing props for the other prop in the same sub-union.

defineProps<
  | {
      a: string
      b: number
    }
  | {
      c: string
      d: number
    }
>()

// Usage
<Comp a="foo" /> // Should trigger missing required prop warning only for `b`

Limitations

  • [x] Requires https://github.com/vuejs/core/pull/12077 for union type-safety.

Supported patterns

This proposal currently supports the following patters:

Discriminated union example

const props = defineProps<
  | {
      tag: string
      d1: number
    }
  | {
      tag: string
      d2: string
    }
>()

// Union definition:
{
  tag: [['d1'], ['d2']],
  d1: ['tag'],
  d2: ['tag']
}

// Usage:
<Comp tag="asdf" :d1="1" /> // Should not warn regarding missing `d2`

Distributive union example

defineProps<
  | {
      a: string
      b: number
    }
  | {
      c: string
      d: number
    }
>()

// Union definition:
{
  a: ['b'],
  b: ['a'],
  c: ['d'],
  d: ['c'],
}

// Usage
<Comp a="foo" /> // Should trigger missing required prop warning only for `b`

Mentions

Shoutout to @KazariEX for helping me navigating various intricacies of the prop type system.

davidmatter avatar Sep 27 '24 14:09 davidmatter