Skip to content

vue-query: support MaybeRefOrGetter for generated hook parameters #3412

Description

@melan0802

Description

TanStack Vue Query v5 recommends using getter functions (() => value) as the idiomatic way to pass reactive parameters to useQuery, and explicitly states: "For trivial cases of simple property access, computed is an optimization with no real benefit." Vue 3.3+ introduced MaybeRefOrGetter<T> (= T | Ref<T> | (() => T)) and toValue() to standardize this pattern. However, orval's vue-query template currently wraps all parameters with MaybeRef<T> via vueWrapTypeWithMaybeRef, which only accepts T | Ref<T> and leaves out getter functions entirely.

Current behavior

Generated hook signature:

import { unref } from 'vue';
import type { MaybeRef } from 'vue';

export const getCustomerDetail = (
  customerId: MaybeRef<number>,  // ❌ getter () => number not accepted
  ...
) => {
  customerId = unref(customerId); // unref() ignores getter functions
  ...
};

Callers who follow TanStack's recommended getter pattern get a type error and must wrap manually:

// Recommended by TanStack Vue Query docs — but orval rejects this
useGetCustomerDetail(() => props.customerId)

// Must wrap in computed instead
const idRef = computed(() => props.customerId ?? 0)
useGetCustomerDetail(idRef, { query: { enabled: computed(() => !!props.customerId) } })

Proposed behavior

import { toValue } from 'vue';
import type { MaybeRefOrGetter } from 'vue';

export const getCustomerDetail = (
  customerId: MaybeRefOrGetter<number>, // ✅ accepts T | Ref<T> | (() => T)
  ...
) => {
  customerId = toValue(customerId); // toValue() handles all three forms
  ...
};

Callers can use the idiomatic getter pattern directly:

useGetCustomerDetail(() => props.customerId) // ✅ no wrapper needed

Proposed solution

The change is localized to vueWrapTypeWithMaybeRef in packages/query/src/frameworks/vue.ts:

  1. Replace the generated type MaybeRef<T>MaybeRefOrGetter<T>
  2. Replace import type { MaybeRef } from 'vue'import type { MaybeRefOrGetter } from 'vue'
  3. Replace the call-site unref(param)toValue(param) for path/query params

MaybeRefOrGetter is a superset of MaybeRef, so existing call sites passing Ref or plain values continue to work without changes. An opt-in config flag (e.g. query.useMaybeRefOrGetter: true) could be added to avoid breaking existing projects.

Metadata

Metadata

Assignees

Labels

vueVue related issue

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions