The legacy widget block preserves what it cannot convert

A registered widget with no block equivalent renders inside a legacy widget block, which keeps it working and keeps it visible as unfinished.

// hide a widget from the legacy block's picker, so
// editors cannot add new instances of something deprecated
add_filter( 'widget_types_to_hide_from_legacy_widget_block',
    function ( array $types ): array {
        $types[] = 'turkerdev_old_promo';

        return $types;
    }
);

// existing instances keep rendering. only the picker changes.

Hiding from the picker while keeping existing instances working is the right shape for a deprecation: nothing breaks and nothing new is created. It also gives a countable measure of progress, since the number of remaining instances is a database query. The legacy block calls the widget’s own render method, so anything that worked before works now — including a widget that echoed instead of returning, which is most of them.