Skip to content

Conversation

@ilhan007
Copy link
Contributor

@ilhan007 ilhan007 commented Jan 27, 2026

Background

Creates unique symbols and marks all slots of all web components so they can be extracted in TS environment.
The specific benefit is for the suggestion and autocompletion of the slots in Vue templates, but same applies in general to other templates supporting Typescript.

Currently all classes have the system _jsxProps and it includes all class members, including slots, but it's not possible to get which members are exactly slots.

Wrapping the current slot types with Slot and DefaultSlot will mark the slots, so that they can be extracted from _jsxPprops.

// Create a unique symbol as a marker
declare const SlotMarker: unique symbol;
declare const DefaultSlotMarker: unique symbol;

export type Slot<T> = T & { [SlotMarker]: true };
export type DefaultSlot<T> = T & { [DefaultSlotMarker]: true };

Changes in Components

In the components we nee to make the following change:

  • current named slots
@slot()
header!: Array<HTMLElement>;
  • now start using the Slot type
import type { Slot } from "@ui5/webcomponents-base/dist/UI5Element.js";

@slot()
header!: Slot<Array<HTMLElement>>;
  • and the current default slots
@slot({
	type: HTMLElement,
	"default": true,
	invalidateOnChildChange: true,
})
items!: Array<ListItemBase | ListItemGroup>;
  • now start using the DefaultSlot type
import type { DefaultSlot } from "@ui5/webcomponents-base/dist/UI5Element.js";

@slot({
	type: HTMLElement,
	"default": true,
	invalidateOnChildChange: true,
})
items!: DefaultSlot<Array<ListItemBase | ListItemGroup>>;

What This Enables?

This makes slots discoverable,
for example the following code extracts an union of the component slot names:

type ExtractSlots<T> = {
        [K in keyof T]: IsDefaultSlot<NonNullable<T[K]>> extends true 
	? "default"
	: IsSlot<NonNullable<T[K]>> extends true 
		? K
 		: never
 [keyof T];

// union of the slot names ("header" | "footer" | "default")
type DialogSlots = Exclude<ExtractSlots<Dialog>, undefined>; 

let a: DialogSlots;

 a = "footer" // ok
 a = "default" // ok
 a = "header"  // ok
 a = "wrong" // error

@ui5-webcomponents-bot
Copy link
Collaborator

ui5-webcomponents-bot commented Jan 27, 2026

@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 27, 2026 13:46 Inactive
@ui5-webcomponents-bot ui5-webcomponents-bot temporarily deployed to preview January 27, 2026 14:19 Inactive
@nnaydenow
Copy link
Contributor

nnaydenow commented Jan 27, 2026

Something to discuss:

  • Slots are always arrays. Can we remove Array from types?
    From:
items!: DefaultSlot<Array<ListItemBase | ListItemGroup>>

To

items!: DefaultSlot<ListItemBase | ListItemGroup>
  • Can we remove the ! from all slot declaration somehow because slots are always defined with empty array?

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.

4 participants