How can I add a constraint to a custom field I created? I have created a complex field type (my class extends DateRangeItem) that supports recurring dates by adding a property for storing an RRULE string:

class DateTimeRecurItem extends DateRangeItem {

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties = parent::propertyDefinitions($field_definition);
    // Prevent early t() calls by using the TranslatableMarkup.
    $properties['rrule_string'] = DataDefinition::create('string')
      -&gt;setLabel(new TranslatableMarkup('RRule String'))
      -&gt;setRequired(FALSE);

    return $properties;
  }

  ...


I want to validate the RRule string (there's a RFC to validate it against). I can do this by creating a custom constraint and applying it like this:

$properties['rrule_string'] = DataDefinition::create('string')
  -&gt;setLabel(new TranslatableMarkup('RRule String'))
  -&gt;setConstraint('MyCustomConstraint')
  -&gt;setRequired(FALSE);


The problem is I also need to know the value for the value property of the field (which is inherited by DateRangeItem). Implemented as above, my constraint validator will only be passed the raw string value of the rrule_string property.

I can't figure out how I can define a constraint that applies to the entire field (thereby having access to all of its field properties). There seems to be no interface for doing that.

To be clear, this is not a field I've added to a custom entity definition. This is just a custom field I defined that can be added to any entity.
In case of a field type, you can simply put it in the annotation.

Have a look at FileItem for example:

/**
 * Plugin implementation of the 'file' field type.
 *
 * @FieldType(
 *   id = "file",
 *   label = @Translation("File"),
 *   description = @Translation("This field stores the ID of a file as an integer value."),
 *   category = @Translation("Reference"),
 *   default_widget = "file_generic",
 *   default_formatter = "file_default",
 *   list_class = "\Drupal\file\Plugin\Field\FieldType\FileFieldItemList",
 *   constraints = {"ReferenceAccess" = {}, "FileValidation" = {}}
 * )
 */
class FileItem extends EntityReferenceItem {


Actually a bit surprised that the date classes don't have any constraints, that sounds like a bug.