-
-
Notifications
You must be signed in to change notification settings - Fork 173
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
Type Support: Properties with conditional types #835
Comments
My first thought was to do something along these lines: diff --git a/packages/oruga/src/components/dropdown/Dropdown.vue b/packages/oruga/src/components/dropdown/Dropdown.vue
index 589d4e3f..0ea6ed52 100644
--- a/packages/oruga/src/components/dropdown/Dropdown.vue
+++ b/packages/oruga/src/components/dropdown/Dropdown.vue
@@ -1,5 +1,12 @@
<script setup lang="ts">
-import { computed, nextTick, ref, watch, type PropType } from "vue";
+import {
+ computed,
+ nextTick,
+ ref,
+ watch,
+ type PropType,
+ type ComponentObjectPropsOptions,
+} from "vue";
import PositionWrapper from "../utils/PositionWrapper.vue";
@@ -35,11 +42,6 @@ defineOptions({
const props = defineProps({
/** Override existing theme classes completely */
override: { type: Boolean, default: undefined },
- /** @model */
- modelValue: {
- type: [String, Number, Boolean, Object, Array],
- default: undefined,
- },
/** The active state of the dropdown, use v-model:active to make it two-way binding. */
active: { type: Boolean, default: false },
/** Trigger label, unnecessary when trgger slot is used */
@@ -85,8 +87,6 @@ const props = defineProps({
type: String,
default: () => getOption("dropdown.animation", "fade"),
},
- /** Allows multiple selections */
- multiple: { type: Boolean, default: false },
/** Trap focus inside the dropdown. */
trapFocus: {
type: Boolean,
@@ -237,6 +237,27 @@ const props = defineProps({
type: [String, Array, Function] as PropType<ComponentClass>,
default: undefined,
},
+ ...({
+ /** @model */
+ modelValue: {
+ type: [String, Number, Boolean, Object, Array],
+ default: undefined,
+ },
+ /** Allows multiple selections */
+ multiple: { type: Boolean, default: false },
+ } satisfies ComponentObjectPropsOptions as
+ | {
+ modelValue: {
+ type: PropType<string | number | boolean | object>;
+ };
+ multiple: { type: PropType<false> };
+ }
+ | {
+ modelValue: {
+ type: PropType<(string | number | boolean | object)[]>;
+ };
+ multiple: { type: PropType<true> };
+ }),
});
const emits = defineEmits<{ I'm not sure that this will actually play nicely with the |
I maybe found a solution explained in this quide: https://medium.com/@ademyalcin27/crafting-type-safe-components-in-vue-js-with-typescript-3724276c6155 I created an example PR for the input component #884. |
Based on a quick glance at the PR, it seems like a pretty reasonable approach. I'd be tempted to use |
And a better name for the type type T = TNumber extends true ? number : string; --> type ConditionalNumberOrString = TNumber extends true ? number : string; /**
* @type string | number
* @model
*/
modelValue?: ConditionalNumberOrString; |
Hmm, I don't like that it is not possible to define the conditional type with the runtime declaration approach and we have to use the type-based declaration approach with the |
Even the types in the component look fine, my example does not work anymore :/ I think this is not the right solution... |
Description
Some components work with different
modelValue
values based on another property.For example, the
modelValue
property of the dropdown component can be a single value, or if themultiple
property istrue
, themodelValue
property will be an array of values.These type distinctions could be solved by using conditional types for such use cases.
Help wanted:
But I don't know how to implement conditional types with the composition api. A similar question can be found here: stackoverflow.
Any suggestions for implementation are welcome.
Why Oruga need this feature
Improve component TypeScript support.
The text was updated successfully, but these errors were encountered: