Skip to content

fix(tree,treeselect,organizationchart): enable generic type inference for value/options and slots#8497

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

fix(tree,treeselect,organizationchart): enable generic type inference for value/options and slots#8497
YevheniiKotyrlo wants to merge 1 commit intoprimefaces:masterfrom
YevheniiKotyrlo:fix/tree-family-generics

Conversation

@YevheniiKotyrlo
Copy link

@YevheniiKotyrlo YevheniiKotyrlo commented Mar 14, 2026

Defect Fixes

Fixes #8496

Tree, TreeSelect, and OrganizationChart use TreeNode / OrganizationChartNode for their data props and all slot scoped data. Both interfaces have a [key: string]: any index signature. Developers who extend these interfaces with custom properties get no type safety — custom properties resolve to any via the index signature instead of their declared types.

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

Related: #7426, #6041

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

Problem

interface MyTreeNode extends TreeNode {
  customLabel: string;
  customIcon?: string;
}

const nodes: MyTreeNode[] = [
  { key: '1', customLabel: 'Root', children: [] }
];
<Tree :value="nodes">
  <template #default="{ node }">
    {{ node.customLabel }}
    <!-- No error — `node.customLabel` is `any` (from index signature), typo ships to production -->
  </template>
</Tree>

After this fix, TypeScript infers T = MyTreeNode from the :value binding and flows it to all slots:

<Tree :value="nodes">
  <template #default="{ node }">
    {{ node.customLabel }}
    <!-- node.customLabel is `string` — proper type from MyTreeNode -->
  </template>
</Tree>

Changes

Tree:

  • TreeProps<T extends TreeNode = TreeNode>value: T[], filterBy callback (node: T) => string
  • TreeSlots<T extends TreeNode = TreeNode> — all 5+ slots with node: T, catch-all [key: string]: (node: T) => VNode[]
  • Generic constructor replaces DefineComponent

TreeSelect:

  • TreeSelectProps<T extends TreeNode = TreeNode>options: T[], modelValue: T | any, filterBy callback (node: T) => string
  • TreeSelectSlots<T extends TreeNode = TreeNode>node: T in option/toggle slots (removes incorrect | any), options: T[] in header/footer
  • Generic constructor with & TreeSelectMethods

OrganizationChart:

  • OrganizationChartProps<T extends OrganizationChartNode = OrganizationChartNode>value: T
  • OrganizationChartSlots<T extends OrganizationChartNode = OrganizationChartNode>node: T in default slot, catch-all [key: string]: (node: T) => VNode[]
  • Generic constructor replaces DefineComponent

What gets typed

Slot / Prop Before After
Tree #default node TreeNode T
Tree #nodeicon / #nodetoggleicon node TreeNode T
Tree catch-all [key: string] node any T
TreeSelect #option node TreeNode | any T
TreeSelect #header / #footer options TreeNode[] T[]
OrganizationChart #default node any T
OrganizationChart catch-all [key: string] node any T

Scope / Impact

  • No breaking changes — backward compatible, T defaults to TreeNode / OrganizationChartNode
  • No runtime changes — types only (.d.ts files)
  • 3 components: Tree, TreeSelect, OrganizationChart

Verification

Gate Result
pnpm run format:check PASS
pnpm run lint PASS
pnpm run test:unit Pre-existing failures only, 0 new
pnpm run build:packages Pre-existing Windows build issue (NODE_ENV= syntax), 0 new

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 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
#8495 Menubar, Menu, TieredMenu, MegaMenu, ContextMenu, PanelMenu, Breadcrumb, Steps, TabMenu, SplitButton, Dock, SpeedDial Open
#8497 Tree, TreeSelect, OrganizationChart This PR

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.

Tree-family components: generic T not inferred from value/options prop

1 participant