Skip to content

fix(select,multiselect,listbox): enable generic type inference for options and slots#8484

Open
YevheniiKotyrlo wants to merge 1 commit intoprimefaces:masterfrom
YevheniiKotyrlo:fix/select-family-generics
Open

fix(select,multiselect,listbox): enable generic type inference for options and slots#8484
YevheniiKotyrlo wants to merge 1 commit intoprimefaces:masterfrom
YevheniiKotyrlo:fix/select-family-generics

Conversation

@YevheniiKotyrlo
Copy link

@YevheniiKotyrlo YevheniiKotyrlo commented Mar 11, 2026

Defect Fixes

Fixes #8482

Select, MultiSelect, and Listbox use any for their options prop and all slot scoped data. Developers get no IDE autocomplete and no compile-time safety when working with option slots — the most common interaction pattern for these components.

Same root cause as #8442DefineComponent's no-arg constructor prevents generic inference. Same fix pattern as #8444 (DataTable/DatePicker).

Related: #7426, #6041

Reproducer: StackBlitz — run bun run type-check in terminal (0 errors — typo undetected), then bun run patch && bun run type-check (TS2339 — typo caught)

Problem

<Select :options="users" optionLabel="name">
  <template #option="{ option }">
    {{ option.naem }}
    <!-- No error — `option` is `any`, typo ships to production -->
  </template>
</Select>

After this fix, TypeScript infers T = User from the :options binding and propagates it to all slots and callbacks:

<Select :options="users" optionLabel="name">
  <template #option="{ option }">
    {{ option.naem }}
    <!-- TS2339: Property 'naem' does not exist on type 'User' -->
  </template>
</Select>

The template code is identical — only the type inference changes.

Changes

For each component (Select, MultiSelect, Listbox):

  • [Component]Props<T = any>options: T[], callback params (data: T) => ...
  • [Component]Slots<T = any>option: T, options: T[] in header/footer/loader slots
  • Generic constructor: new <T = any>(props: [Component]Props<T>) with $slots: [Component]Slots<T>
  • modelValue stays any — when optionValue is set, the value is the extracted scalar (e.g., string), not the option object (e.g., User). Typing both as T would cause false positives across every consumer that uses optionValue.

What gets typed

Slot/Callback Before After
#option slot option any T
#header / #footer slot options any[] T[]
#optiongroup slot option any T
optionLabel callback param any T
optionValue callback param any T
optionDisabled callback param any T
modelValue any any (unchanged — see above)

Scope / Impact

  • No breaking changes — backward compatible, T defaults to any
  • No runtime changes — types only (.d.ts files)
  • 3 components with identical pattern: Select, MultiSelect, Listbox

Verification

Gate Result
vue-tsc --noEmit with strictTemplates 0 new errors, 1 real bug caught (union of incompatible option arrays in consumer code)
All CI gates (format, lint, test, build) PASS

Series

This is part of a series bringing generic type inference to all PrimeVue data components:

PR Components Status
#8444 DataTable, DatePicker Open
#8484 Select, MultiSelect, Listbox This PR
#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.

Select, MultiSelect, Listbox: options and slots are untyped (any)

1 participant