Props declaration with different types #13995
Unanswered
mtmsFKoechl
asked this question in
Help/Questions
Replies: 1 comment
-
|
Hello! Your approach is almost correct, but you need to use a discriminated union with a common discriminant property. Here's the proper implementation: Solution 1: Discriminated Union with Type Guards <template>
<div>
<div v-if="isTypeA">Type A: {{ foo }}</div>
<div v-else>Type B: {{ foo }} - {{ bar }}</div>
</div>
</template>
<script setup lang="ts">
interface TypeA {
type: 'a';
foo: 'test1' | 'test2';
}
interface TypeB<T = Record<string, any>> {
type: 'b';
foo: 'test';
bar: T;
}
type Props<T = Record<string, any>> = TypeA | TypeB<T>;
const props = defineProps<Props>();
const isTypeA = computed(() => props.type === 'a');
const isTypeB = computed(() => props.type === 'b');
const barValue = computed(() => isTypeB.value ? props.bar : null);
function init() {
if (isTypeB.value) {
console.log('Bar value:', props.bar);
}
}
</script>Solution 2: Using Generic with Conditional Types <script setup lang="ts" generic="T extends Record<string, any>">
type Props<T> =
| { foo: 'test1' | 'test2' }
| { foo: 'test'; bar: T };
const props = defineProps<Props<T>>();
const hasBar = computed(() => props.foo === 'test' && 'bar' in props);
function init() {
if (props.foo === 'test') {
console.log(props.bar);
}
}
</script>Solution 3: With Runtime Validation (Recommended) <script setup lang="ts">
import type { PropType } from 'vue';
type TypeA = {
foo: 'test1' | 'test2';
}
type TypeB<T = any> = {
foo: 'test';
bar: T;
}
const props = defineProps({
foo: {
type: String as PropType<'test1' | 'test2' | 'test'>,
required: true,
validator: (value: string) => ['test1', 'test2', 'test'].includes(value)
},
bar: {
type: Object as PropType<Record<string, any>>,
required: false,
default: undefined
}
});
const isTypeB = computed(() => props.foo === 'test');
const barValue = computed(() => isTypeB.value ? props.bar : null);
function init() {
if (isTypeB.value && props.bar) {
console.log(props.bar);
}
}
</script>Key Points:
The discriminated union pattern (Solution 1) is generally the most maintainable approach for complex prop type scenarios. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Hi,
firstly, I would like to thank you for this excellent framework.
I really appreciate Vue 3 and the Composition API.
However, I now need some help.
Here is a short demo showing what I am trying to do.
The goal is that if 'foo' has the value 'test', then the 'bar' prop with the generic type should be required.
My question is: is this possible, or have I made a mistake in the type definition? Or do I need to use "defineComponent"?
Please note that the types are in a private TypeScript package and the component is in a private Vue components package.
Thank you in advance for your help.
Beta Was this translation helpful? Give feedback.
All reactions