Breaking: #107823 - Strict typing and API cleanup in backend template components
See forge#107823
Description
The backend template components system (buttons, dropdown items, and menus) has been modernized with strict type hints, consistent return types, and improved architecture to enhance type safety and developer experience.
Impact
Extensions that implement or extend backend template components must verify their type declarations and update any usage of changed methods.
New ComponentInterface
A new
\TYPO3\
has been introduced as the parent interface for both
\Button and
\Drop.
This unifies the common contract for all renderable backend components.
Both interfaces now extend
Component,
which defines:
isValid (): bool getType (): string render(): string
Custom implementations of
\Button
or
\Drop will
now trigger a
\Type if these return types are missing.
PositionInterface enforced
The
\TYPO3\ now enforces
strict type hints:
getPosition (): string getGroup (): int
This interface allows buttons to define their own fixed position and group,
which automatically override the position and group parameters passed to
Button.
Icon nullability
Icons are now consistently nullable across all button types. The
Abstract property and related getter/setter methods now use
?Icon instead of
Icon.
This affects classes extending
Abstract, including
Link,
Input, and
Split.
Note
While icons are technically optional at the type level, validation methods may still require icons for buttons to be considered valid.
Method signature changes
Several methods now have stricter parameter types or modified signatures:
MenuandItem:: is Valid () Menu::no longer accept parametersis Valid () Abstractnow declares aDrop Down Item:: render () stringreturn type- Various setter methods now require strict type hints for their parameters
Return type consistency
Abstract classes now use
static return types for better inheritance
support, while concrete implementations may use
self or
static
depending on extensibility requirements.
SplitButton API improvement
The
Split method has been replaced with
get, which returns a type-safe
Split DTO
instead of an untyped array.
Old (removed):
public function getButton(): array // Returns array with magic keys 'primary' and 'options'
New:
public function getItems(): SplitButtonItems // Returns typed DTO
The
Split DTO provides:
public readonly Abstract- The primary action buttonButton $primary public readonly array $options- Array of option buttons
This change improves type safety and prevents runtime errors from accessing non-existent array keys.
Affected installations
All TYPO3 instances with custom backend components, such as buttons, menus, or dropdown items, that extend or implement the affected interfaces are impacted.
Migration
Extension authors should:
- Verify custom button implementations have correct return types on interface methods.
- Check custom classes extending abstract buttons use proper strict types.
- Update `isValid()` calls on
MenuandItem Menuobjects (remove the parameter). - Handle nullable icons when working with
getmethods.Icon ()
Example: implementing ButtonInterface
use TYPO3\CMS\Backend\Template\Components\ButtonInterface;
// Before
class CustomButton implements ButtonInterface {
public function isValid() { ... }
public function render() { ... }
public function getType() { ... }
}
use TYPO3\CMS\Backend\Template\Components\ButtonInterface;
// After
class CustomButton implements ButtonInterface {
public function isValid(): bool { ... }
public function render(): string { ... }
public function getType(): string { return static::class; }
}
Example: nullable icons
// Handle nullable icon return
$icon = $button->getIcon(); // Now returns ?Icon
$html = $icon?->render() ?? '';
Example: using SplitButton with typed DTO
If you were directly accessing the
get method:
// Before
$items = $splitButton->getButton();
$primary = $items['primary']; // Magic string key
$options = $items['options']; // Magic string key
// After
$items = $splitButton->getItems();
$primary = $items->primary; // Type-safe property access
$options = $items->options; // Type-safe property access