To get this working I had to create a hidden field to store the value and hijack the drupal autocompleteselect handler in JavaScript. I added a class check on the autocomplete field to hopefully not disturb other autocompletes.

**JavaScript File**

    (function ($, Drupal) {

      'use strict';

      /**
       * Override drupal selectHandler function
       */
      function customSelectHandler(event, ui) {
        var valueField = $(event.target);
        if($(event.target).hasClass('MYCUSTOM-autocomplete')) {
          var valueFieldName = event.target.name+'_value';
          if($('input[name='+valueFieldName+']').length > 0) {
            valueField = $('input[name='+valueFieldName+']');
            // update the labels too
            const labels = Drupal.autocomplete.splitValues(event.target.value);
            labels.pop();
            labels.push(ui.item.label);
            event.target.value = labels.join(', ');
          }
        }
        const terms = Drupal.autocomplete.splitValues(valueField.val());
        // Remove the current input.
        terms.pop();
        // Add the selected item.
        terms.push(ui.item.value);

        valueField.val(terms.join(', '));
        // Return false to tell jQuery UI that we've filled in the value already.
        return false;
      }
      // override drupal.autocomplete object with custom selectHandler function
      if(typeof Drupal.autocomplete != "undefined") Drupal.autocomplete.options.select = customSelectHandler;

    })(jQuery, Drupal);

**Form PHP**

    $form['my_field'] = array(
      '#type' => 'textfield',
      '#title' => 'My Field',
      '#attributes' => [
        'class' => ['MYCUSTOM-autocomplete'],
      ],
      '#autocomplete_route_name' => 'mymodule.myfield_autocomplete',
      '#default_value' => '',
    );
    // field value
    $form['my_field_value'] = array(
      '#type' => 'hidden',
      '#value' => '', // default value can go here
    );

On our forms we also have an AJAX callback on the autocompleteselect event, and I've noticed the value for the hidden field is blank but the userInput on the $form_state has the value.

Problem with this is the splitValues function may not work well for the labels, since it appears to be comma-delimited. You may want to write your own to handle it. It also won't work well if using the same form twice on a page, but there may be a way to narrow down the selector on the hidden field.