I have 2 props: modelValue
and range
. The type of modelValue
is conditional on the value of range
. If true, I want modelValue
to be of the type [number, number]
; if false, I want modelValue
to have the type number
.
interface SharedProps { ...rest of props }
type Props = SharedProps & ( | { range: true; modelValue: [number, number] } | { range?: false; modelValue: number } )
const props = defineProps<Props>()
const emit = defineEmits<{ (e: 'update:modelValue', value: typeof props.modelValue): void }>()
// Destructure with defaults const { modelValue, range, ...rest of props } = props
Now in my component this works:
const tempValue = ref<number>(10) <VelSliderInput v-model="tempValue" :max="10" :min="0" />
and when I add range
as a prop:
<VelSliderInput
v-model="tempValue"
:max="10"
range
:min="0"
/>
I get the error as expected:
Argument of type '{ modelValue: number; max: number; range: true; min: number; }' is not assignable to parameter of type ...
Types of property 'modelValue' are incompatible.
Type 'number' is not assignable to type '[number, number]'.
Now when I use :model-value
and @update:model-value
:
<VelSliderInput
:model-value="tempValue"
:max="10"
:min="0"
@update:model-value="tempValue = $event"
/>
I get the error:
Type 'number | [number, number]' is not assignable to type 'number'.
Type '[number, number]' is not assignable to type 'number'.
Probably because in my emit I'm using a union type and not a discriminated union / conditional type.
Question: how can I emit a discriminated union / conditional type, so that I don't need to type cast in my component?