Skip to content

fix(datatable,datepicker): enable generic type inference for T, F, and V#8444

Open
YevheniiKotyrlo wants to merge 2 commits intoprimefaces:masterfrom
YevheniiKotyrlo:fix/generic-type-inference
Open

fix(datatable,datepicker): enable generic type inference for T, F, and V#8444
YevheniiKotyrlo wants to merge 2 commits intoprimefaces:masterfrom
YevheniiKotyrlo:fix/generic-type-inference

Conversation

@YevheniiKotyrlo
Copy link

@YevheniiKotyrlo YevheniiKotyrlo commented Feb 17, 2026

Defect Fixes

Fixes #8442

DataTable and DatePicker lose type specificity through DefineComponent's no-arg constructor. This completes #7427, which made DataTableProps<T> generic but left the component declaration using DefineComponent with new () — so T is never inferred from template bindings. Users are still reporting this in #7426.

Related: #7426, #6041, #7838

Reproducer: StackBlitzbun run type-check (0 errors, typo undetected) → bun run patch && bun run type-check (TS2339 catches it)

Problem

<DataTable :value="orders" v-model:filters="filters">
  <template #groupheader="{ data }">
    {{ data.stauts }}
    <!-- No error — `data` is `any`, typo ships to production -->
  </template>
</DataTable>

After this fix, TypeScript infers T from :value and F from v-model:filters:

<DataTable :value="orders" v-model:filters="filters">
  <template #groupheader="{ data }">
    {{ data.stauts }}
    <!-- TS2339: Property 'stauts' does not exist on type 'Order' -->
  </template>
</DataTable>

The template code is identical — only the type inference changes. v-model:filters also emits the consumer's specific filter type instead of the widest DataTableFilterMeta union.

Root cause

PrimeVue's DefineComponent uses new () (no-arg constructor). vue-tsc generates new Component({...props...}) in template codegen and infers K from the instance. But with a no-arg constructor, InstanceType<T> erases generic parameters to defaults.

When the constructor accepts props (new <T, F>(props: P)), TypeScript infers generics from the actual prop values — and vue-tsc's existing codegen makes this work automatically.

Scope / Impact

  • No breaking changes — backward compatible via @ts-ignore in vue-tsc codegen
  • No runtime changes — types only
  • No behavioral changes — defaults match current types exactly

This aligns with the approach used in #8287 (generic DynamicDialogCloseOptions) and builds on the foundation from #7427.

Changes

DataTable — T (row data) + F (filters):

  • Add generic T to constructor — inferred from :value binding, flows to $slots and $emit
  • Add generic F extends DataTableFilterMeta to constructor — inferred from v-model:filters
  • Change sortField from keyof T to HintedString<keyof T & string> — when T is inferred (not any), keyof T becomes a strict union that breaks consumers passing plain strings. HintedString accepts any string but provides autocomplete for known keys (the same pattern already used for alignFrozen, selectionMode, etc.)
  • NoInfer<T> on secondary props (selection, expandedRows) prevents T from being inferred from the wrong source — only from :value
Feature Before (T = any) After (T inferred from :value)
sortField accepts any string autocomplete for keyof T keys
#groupheader / #groupfooter / #expansion slot data any typed as T
rowClass / rowStyle callback param any typed as T

DatePicker — V (model value):

  • Add generic V to constructor — inferred from v-model binding
  • 'update:modelValue' and 'value-change' emit the specific V type instead of the widest union

How it works

vue-tsc already generates new DataTable({ value: orders.value, filters: filters.value }) in template codegen. With the generic constructor, TypeScript infers T from value and F from filters, and the emit callbacks receive the same types — making v-model:filters and slot scoped data fully type-safe.

Verification

Gate Result
vue-tsc --noEmit with strictTemplates All DataTable/DatePicker type errors eliminated, 0 introduced
sortField with HintedString<keyof T & string> Accepts any string, provides autocomplete
NoInfer<T> on selection/expandedRows T only inferred from :value
Backward compat (non-generic use) @ts-ignore in vue-tsc codegen handles it
All CI gates (format, lint, test, security, build) PASS

Series

This is the first PR in a series bringing generic type inference to all PrimeVue data components:

PR Components Status
#8444 DataTable, DatePicker This PR
#8484 Select, MultiSelect, Listbox Open
#8485 Column (phantom of prop) Open
#8489 AutoComplete, CascadeSelect, DataView Open
#8490 Carousel, Galleria, Timeline Open
#8491 OrderList, PickList Open
#8493 VirtualScroller, SelectButton, InputChips Open

After this series, every PrimeVue component with a collection prop will infer T from the binding and flow it to slots — giving developers full IDE autocomplete and compile-time type safety in templates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DataTable v-model:filters and DatePicker v-model lose type specificity (DefineComponent no-arg constructor)

1 participant