diff --git a/core/lib/Drupal/Core/Entity/ContentEntityBase.php b/core/lib/Drupal/Core/Entity/ContentEntityBase.php index a8fc193..7d53cb9 100644 --- a/core/lib/Drupal/Core/Entity/ContentEntityBase.php +++ b/core/lib/Drupal/Core/Entity/ContentEntityBase.php @@ -10,6 +10,7 @@ use Drupal\Core\Entity\Plugin\DataType\EntityReference; use Drupal\Core\Language\Language; use Drupal\Core\Session\AccountInterface; +use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\TypedData\TypedDataInterface; /** @@ -226,7 +227,7 @@ public function getDefinition() { else { $type = 'entity:' . $this->entityType(); } - return array('type' => $type); + return DataDefinition::create($type); } /** diff --git a/core/lib/Drupal/Core/Entity/EntityManager.php b/core/lib/Drupal/Core/Entity/EntityManager.php index 2bce05d..ed359f6 100644 --- a/core/lib/Drupal/Core/Entity/EntityManager.php +++ b/core/lib/Drupal/Core/Entity/EntityManager.php @@ -338,15 +338,8 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) { // See https://drupal.org/node/2114707. $class = $this->factory->getPluginClass($entity_type, $this->getDefinition($entity_type)); - $base_definitions = $class::baseFieldDefinitions($entity_type); - foreach ($base_definitions as &$base_definition) { - // Support old-style field types to avoid that all base field - // definitions need to be changed. - // @todo: Remove after https://drupal.org/node/2047229. - $base_definition['type'] = preg_replace('/(.+)_field/', 'field_item:$1', $base_definition['type']); - } $this->entityFieldInfo[$entity_type] = array( - 'definitions' => $base_definitions, + 'definitions' => $class::baseFieldDefinitions($entity_type), // Contains definitions of optional (per-bundle) fields. 'optional' => array(), // An array keyed by bundle name containing the optional fields added @@ -360,13 +353,9 @@ public function getFieldDefinitions($entity_type, $bundle = NULL) { $result = $this->moduleHandler->invokeAll('entity_field_info', array($entity_type)); $this->entityFieldInfo[$entity_type] = NestedArray::mergeDeep($this->entityFieldInfo[$entity_type], $result); - // Enforce field definitions to be objects. + // Automatically set the field name for non-configurable fields. foreach (array('definitions', 'optional') as $key) { foreach ($this->entityFieldInfo[$entity_type][$key] as $field_name => &$definition) { - if (is_array($definition)) { - $definition = FieldDefinition::createFromOldStyleDefinition($definition); - } - // Automatically set the field name for non-configurable fields. if ($definition instanceof FieldDefinition) { $definition->setFieldName($field_name); } diff --git a/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageReference.php b/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageReference.php index a4c061f..f0c352c 100644 --- a/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageReference.php +++ b/core/lib/Drupal/Core/Entity/Plugin/DataType/LanguageReference.php @@ -7,9 +7,8 @@ namespace Drupal\Core\Entity\Plugin\DataType; +use Drupal\Core\TypedData\DataDefinition; use Drupal\Core\TypedData\DataReferenceBase; -use Drupal\Core\TypedData\Annotation\DataType; -use Drupal\Core\Annotation\Translation; /** * Defines the 'language_reference' data type. @@ -32,9 +31,7 @@ class LanguageReference extends DataReferenceBase { * {@inheritdoc} */ public function getTargetDefinition() { - return array( - 'type' => 'language', - ); + return DataDefinition::create('language'); } /** diff --git a/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php b/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php index b4c6720..bbd1747 100644 --- a/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php +++ b/core/lib/Drupal/Core/Field/ConfigEntityReferenceItemBase.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Field; use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem; +use Drupal\Core\TypedData\DataDefinition; use Drupal\field\FieldInstanceInterface; use Drupal\field\FieldInterface; @@ -35,11 +36,12 @@ class ConfigEntityReferenceItemBase extends EntityReferenceItem implements Confi * {@inheritdoc} */ public function getPropertyDefinitions() { - $target_type = $this->definition['settings']['target_type']; + $settings = $this->definition->getSettings(); + $target_type = $settings['target_type']; // Definitions vary by entity type and bundle, so key them accordingly. $key = $target_type . ':'; - $key .= isset($this->definition['settings']['target_bundle']) ? $this->definition['settings']['target_bundle'] : ''; + $key .= isset($settings['target_bundle']) ? $settings['target_bundle'] : ''; if (!isset(static::$propertyDefinitions[$key])) { // Call the parent to define the target_id and entity properties. @@ -49,25 +51,18 @@ public function getPropertyDefinitions() { // revisions. $target_type_info = \Drupal::entityManager()->getDefinition($target_type); if (!empty($target_type_info['entity_keys']['revision']) && !empty($target_type_info['revision_table'])) { - static::$propertyDefinitions[$key]['revision_id'] = array( - 'type' => 'integer', - 'label' => t('Revision ID'), - 'constraints' => array( - 'Range' => array('min' => 0), - ), - ); + static::$propertyDefinitions[$key]['revision_id'] = DataDefinition::create('integer') + ->setLabel(t('Revision ID')) + ->setConstraints(array('Range' => array('min' => 0))); } - static::$propertyDefinitions[$key]['label'] = array( - 'type' => 'string', - 'label' => t('Label (auto-create)'), - 'computed' => TRUE, - ); - static::$propertyDefinitions[$key]['access'] = array( - 'type' => 'boolean', - 'label' => t('Access'), - 'computed' => TRUE, - ); + static::$propertyDefinitions[$key]['label'] = DataDefinition::create('string') + ->setLabel(t('Label (auto-create)')) + ->setComputed(TRUE); + + static::$propertyDefinitions[$key]['access'] = DataDefinition::create('boolean') + ->setLabel(t('Access')) + ->setComputed(TRUE); } return static::$propertyDefinitions[$key]; } diff --git a/core/lib/Drupal/Core/Field/FieldDefinition.php b/core/lib/Drupal/Core/Field/FieldDefinition.php index 640bee3..d33da70 100644 --- a/core/lib/Drupal/Core/Field/FieldDefinition.php +++ b/core/lib/Drupal/Core/Field/FieldDefinition.php @@ -14,7 +14,7 @@ /** * A class for defining entity fields. */ -class FieldDefinition extends ListDefinition implements FieldDefinitionInterface, \ArrayAccess { +class FieldDefinition extends ListDefinition implements FieldDefinitionInterface { /** * Creates a new field definition. @@ -251,77 +251,4 @@ public function getFieldDefaultValue(EntityInterface $entity) { return $this->getFieldSetting('default_value'); } - /** - * Allows creating field definition objects from old style definition arrays. - * - * @todo: Remove once https://drupal.org/node/2112239 is in. - */ - public static function createFromOldStyleDefinition(array $definition) { - unset($definition['list']); - - // Separate the list item definition from the list definition. - $list_definition = $definition; - unset($list_definition['type']); - - // Constraints, class and settings apply to the list item. - unset($list_definition['constraints']); - unset($list_definition['class']); - unset($list_definition['settings']); - - $field_definition = new FieldDefinition($list_definition); - if (isset($definition['list_class'])) { - $field_definition->setClass($definition['list_class']); - } - else { - $type_definition = \Drupal::typedData()->getDefinition($definition['type']); - if (isset($type_definition['list_class'])) { - $field_definition->setClass($type_definition['list_class']); - } - } - if (isset($definition['translatable'])) { - $field_definition->setTranslatable($definition['translatable']); - unset($definition['translatable']); - } - - // Take care of the item definition now. - // Required applies to the field definition only. - unset($definition['required']); - $item_definition = new DataDefinition($definition); - $field_definition->setItemDefinition($item_definition); - return $field_definition; - } - - /** - * {@inheritdoc} - * - * This is for BC support only. - * @todo: Remove once https://drupal.org/node/2112239 is in. - */ - public function &offsetGet($offset) { - if ($offset == 'type') { - // What previously was "type" is now the type of the list item. - $type = &$this->itemDefinition->offsetGet('type'); - return $type; - } - if (!isset($this->definition[$offset])) { - $this->definition[$offset] = NULL; - } - return $this->definition[$offset]; - } - - /** - * {@inheritdoc} - * - * This is for BC support only. - * @todo: Remove once https://drupal.org/node/2112239 is in. - */ - public function offsetSet($offset, $value) { - if ($offset == 'type') { - // What previously was "type" is now the type of the list item. - $this->itemDefinition->setDataType($value); - } - else { - $this->definition[$offset] = $value; - } - } } diff --git a/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php index 4645936..c329ed6 100644 --- a/core/lib/Drupal/Core/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Field/FieldItemBase.php @@ -8,6 +8,7 @@ namespace Drupal\Core\Field; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\TypedData\DataDefinitionInterface; use Drupal\Core\TypedData\Plugin\DataType\Map; use Drupal\Core\TypedData\TypedDataInterface; use Drupal\user; @@ -23,14 +24,18 @@ abstract class FieldItemBase extends Map implements FieldItemInterface { /** - * Overrides \Drupal\Core\TypedData\TypedData::__construct(). + * {@inheritdoc} */ - public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) { + public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) { parent::__construct($definition, $name, $parent); // Initialize computed properties by default, such that they get cloned // with the whole item. foreach ($this->getPropertyDefinitions() as $name => $definition) { - if (!empty($definition['computed'])) { + if (!is_object($definition)) { + echo '
';
+        print_r($definition);
+      }
+      if ($definition->isComputed()) {
         $this->properties[$name] = \Drupal::typedData()->getPropertyInstance($this, $name);
       }
     }
@@ -192,9 +197,9 @@ public function getConstraints() {
     $constraints = parent::getConstraints();
     // If property constraints are present add in a ComplexData constraint for
     // applying them.
-    if (!empty($this->definition['property_constraints'])) {
+    if ($property_constraints = $this->definition->getConstraints()) {
       $constraints[] = \Drupal::typedData()->getValidationConstraintManager()
-        ->create('ComplexData', $this->definition['property_constraints']);
+        ->create('ComplexData', $property_constraints);
     }
     return $constraints;
   }
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index d95c939..51bdc49 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Field;
 
 use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\TypedData\DataDefinitionInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 use Drupal\Core\TypedData\Plugin\DataType\ItemList;
 use Drupal\Core\Language\Language;
@@ -40,7 +41,7 @@ class FieldItemList extends ItemList implements FieldItemListInterface {
   /**
    * {@inheritdoc}
    */
-  public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) {
+  public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
     parent::__construct($definition, $name, $parent);
     // Always initialize one empty item as most times a value for at least one
     // item will be present. That way prototypes created by
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
index fe7ba96..994957c 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/BooleanItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'boolean' entity field type.
@@ -34,13 +35,11 @@ class BooleanItem extends FieldItemBase {
    * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
    */
   public function getPropertyDefinitions() {
-
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'boolean',
-        'label' => t('Boolean value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('boolean')
+        ->setLabel(t('Boolean value'));
     }
     return static::$propertyDefinitions;
   }
+
 }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php
index ce0817c..5a2c107 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EmailItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'email' entity field type.
@@ -36,10 +37,8 @@ class EmailItem extends FieldItemBase {
   public function getPropertyDefinitions() {
 
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'email',
-        'label' => t('E-mail value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('email')
+        ->setLabel(t('E-mail value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
index 61f624f..f773ffd 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/EntityReferenceItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'entity_reference' entity field type.
@@ -41,45 +42,41 @@ class EntityReferenceItem extends FieldItemBase {
    * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
    */
   public function getPropertyDefinitions() {
-    $target_type = $this->definition['settings']['target_type'];
+    $settings = $this->definition->getSettings();
+    $target_type = $settings['target_type'];
 
     // Definitions vary by entity type and bundle, so key them accordingly.
     $key = $target_type . ':';
-    $key .= isset($this->definition['settings']['target_bundle']) ? $this->definition['settings']['target_bundle'] : '';
+    $key .= isset($settings['target_bundle']) ? $settings['target_bundle'] : '';
 
     if (!isset(static::$propertyDefinitions[$key])) {
       $target_type_info = \Drupal::entityManager()->getDefinition($target_type);
       if (is_subclass_of($target_type_info['class'], '\Drupal\Core\Entity\ContentEntityInterface')) {
-        static::$propertyDefinitions[$key]['target_id'] = array(
-          // @todo: Lookup the entity type's ID data type and use it here.
-          // https://drupal.org/node/2107249
-          'type' => 'integer',
-          'label' => t('Entity ID'),
-          'constraints' => array(
+        // @todo: Lookup the entity type's ID data type and use it here.
+        // https://drupal.org/node/2107249
+        static::$propertyDefinitions[$key]['target_id'] = DataDefinition::create('integer')
+          ->setLabel(t('Entity ID'))
+          ->setConstraints(array(
             'Range' => array('min' => 0),
-          ),
-        );
+          ));
       }
       else {
-        static::$propertyDefinitions[$key]['target_id'] = array(
-          'type' => 'string',
-          'label' => t('Entity ID'),
-        );
+        static::$propertyDefinitions[$key]['target_id'] = DataDefinition::create('string')
+          ->setLabel(t('Entity ID'));
       }
 
-      static::$propertyDefinitions[$key]['entity'] = array(
-        'type' => 'entity_reference',
-        'constraints' => array(
-          'EntityType' => $this->definition['settings']['target_type'],
-        ),
-        'label' => t('Entity'),
-        'description' => t('The referenced entity'),
+      static::$propertyDefinitions[$key]['entity'] = DataDefinition::create('entity_reference')
+        ->setLabel(t('Entity'))
+        ->setDescription(t('The referenced entity'))
         // The entity object is computed out of the entity ID.
-        'computed' => TRUE,
-        'read-only' => FALSE,
-      );
-      if (isset($this->definition['settings']['target_bundle'])) {
-        static::$propertyDefinitions[$key]['entity']['constraints']['Bundle'] = $this->definition['settings']['target_bundle'];
+        ->setComputed(TRUE)
+        ->setReadOnly(FALSE)
+        ->setConstraints(array(
+          'EntityType' => $settings['target_type'],
+        ));
+
+      if (isset($settings['target_bundle'])) {
+        static::$propertyDefinitions[$key]['entity']->addConstraint('Bundle', $settings['target_bundle']);
       }
     }
     return static::$propertyDefinitions[$key];
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php
index ccfd3c5..e489a2f 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/FloatItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'float' entity field type.
@@ -36,10 +37,8 @@ class FloatItem extends FieldItemBase {
   public function getPropertyDefinitions() {
 
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'float',
-        'label' => t('Float value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('float')
+        ->setLabel(t('Float value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
index 3ed6127..bd4d877 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/LanguageItem.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Field\FieldItemBase;
 use Drupal\Core\Language\Language;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'language' entity field item.
@@ -41,18 +42,15 @@ class LanguageItem extends FieldItemBase {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'string',
-        'label' => t('Language code'),
-      );
-      static::$propertyDefinitions['language'] = array(
-        'type' => 'language_reference',
-        'label' => t('Language object'),
-        'description' => t('The referenced language'),
-        // The language object is retrieved via the language code.
-        'computed' => TRUE,
-        'read-only' => FALSE,
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('string')
+        ->setLabel(t('Language code'));
+
+      static::$propertyDefinitions['language'] = DataDefinition::create('language_reference')
+        ->setLabel(t('Language object'))
+        ->setDescription(t('The referenced language'))
+      // The language object is retrieved via the language code.
+        ->setComputed(TRUE)
+        ->setReadOnly(FALSE);
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
index 23f9701..c1be221 100644
--- a/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
+++ b/core/lib/Drupal/Core/Field/Plugin/Field/FieldType/UriItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\Core\Field\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'uri' entity field type.
@@ -34,13 +35,11 @@ class UriItem extends FieldItemBase {
    * Implements ComplexDataInterface::getPropertyDefinitions().
    */
   public function getPropertyDefinitions() {
-
     if (!isset(self::$propertyDefinitions)) {
-      self::$propertyDefinitions['value'] = array(
-        'type' => 'uri',
-        'label' => t('URI value'),
-      );
+      self::$propertyDefinitions['value'] = DataDefinition::create('uri')
+        ->setLabel(t('URI value'));
     }
     return self::$propertyDefinitions;
   }
+
 }
diff --git a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php
index 2e3d0e7..438ea6e 100644
--- a/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php
+++ b/core/lib/Drupal/Core/TypedData/ComplexDataInterface.php
@@ -105,7 +105,7 @@ public function getPropertyDefinition($name);
   /**
    * Gets an array of property definitions of contained properties.
    *
-   * @return array
+   * @return \Drupal\Core\TypedData\DataDefinitionInterface[]
    *   An array of property definitions of contained properties, keyed by
    *   property name.
    */
diff --git a/core/lib/Drupal/Core/TypedData/DataDefinition.php b/core/lib/Drupal/Core/TypedData/DataDefinition.php
index a77aea4..ed4709e 100644
--- a/core/lib/Drupal/Core/TypedData/DataDefinition.php
+++ b/core/lib/Drupal/Core/TypedData/DataDefinition.php
@@ -10,7 +10,7 @@
 /**
  * A class for defining data based on defined data types.
  */
-class DataDefinition implements DataDefinitionInterface, \ArrayAccess {
+class DataDefinition implements DataDefinitionInterface {
 
   /**
    * The array holding values for all definition keys.
@@ -25,7 +25,7 @@ class DataDefinition implements DataDefinitionInterface, \ArrayAccess {
    * @param string $type
    *   The data type of the data; e.g., 'string', 'integer' or 'any'.
    *
-   * @return \Drupal\Core\TypedData\DataDefinition
+   * @return static
    *   A new DataDefinition object.
    */
   public static function create($type) {
@@ -56,7 +56,7 @@ public function getDataType() {
    * @param string $type
    *   The data type to set.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setDataType($type) {
@@ -77,7 +77,7 @@ public function getLabel() {
    * @param string $label
    *   The label to set.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setLabel($label) {
@@ -98,7 +98,7 @@ public function getDescription() {
    * @param string $description
    *   The description to set.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setDescription($description) {
@@ -130,7 +130,7 @@ public function isReadOnly() {
    * @param bool $read_only
    *   Whether the data is read-only.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setReadOnly($read_only) {
@@ -151,7 +151,7 @@ public function isComputed() {
    * @param bool $computed
    *   Whether the data is computed.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setComputed($computed) {
@@ -172,7 +172,7 @@ public function isRequired() {
    * @param bool $required
    *   Whether the data is required.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setRequired($required) {
@@ -193,7 +193,7 @@ public function getClass() {
    * @param string|null $class
    *   The class to use.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setClass($class) {
@@ -219,7 +219,7 @@ public function getSettings() {
    * @param array $settings
    *   The array of settings.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setSettings(array $settings) {
@@ -248,7 +248,7 @@ public function getConstraints() {
    * @param array $constraints
    *   The array of constraints.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function setConstraints(array $constraints) {
@@ -266,7 +266,7 @@ public function setConstraints(array $constraints) {
    * @param array|null $options
    *   The constraint options as required by the constraint plugin, or NULL.
    *
-   * @return self
+   * @return static
    *   The object itself for chaining.
    */
   public function addConstraint($constraint_name, $options = NULL) {
@@ -275,51 +275,6 @@ public function addConstraint($constraint_name, $options = NULL) {
   }
 
   /**
-   * {@inheritdoc}
-   *
-   * This is for BC support only.
-   * @todo: Remove once https://drupal.org/node/2112239 is in.
-   */
-  public function offsetExists($offset) {
-    // PHP's array access does not work correctly with isset(), so we have to
-    // bake isset() in here. See https://bugs.php.net/bug.php?id=41727.
-    return array_key_exists($offset, $this->definition) && isset($this->definition[$offset]);
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * This is for BC support only.
-   * @todo: Remove once https://drupal.org/node/2112239 is in.
-   */
-  public function &offsetGet($offset) {
-    if (!isset($this->definition[$offset])) {
-      $this->definition[$offset] = NULL;
-    }
-    return $this->definition[$offset];
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * This is for BC support only.
-   * @todo: Remove once https://drupal.org/node/2112239 is in.
-   */
-  public function offsetSet($offset, $value) {
-    $this->definition[$offset] = $value;
-  }
-
-  /**
-   * {@inheritdoc}
-   *
-   * This is for BC support only.
-   * @todo: Remove once https://drupal.org/node/2112239 is in.
-   */
-  public function offsetUnset($offset) {
-    unset($this->definition[$offset]);
-  }
-
-  /**
    * Returns all definition values as array.
    *
    * @return array
@@ -328,44 +283,4 @@ public function toArray() {
     return $this->definition;
   }
 
-  /**
-   * Allows creating data definition objects from old style definition arrays.
-   *
-   * @todo: Remove once https://drupal.org/node/2112239 is in.
-   */
-  public static function createFromOldStyleDefinition(array $definition) {
-    if (empty($definition['list'])) {
-      return new DataDefinition($definition);
-    }
-
-    // If the definition describes a list, separate the list item definition
-    // from the list definition.
-    unset($definition['list']);
-
-    $list_definition = $definition;
-    unset($list_definition['type']);
-
-    // Constraints, class and settings apply to the list item.
-    unset($list_definition['constraints']);
-    unset($list_definition['class']);
-    unset($list_definition['settings']);
-
-    $list_definition = new ListDefinition($list_definition);
-    if (isset($definition['list_class'])) {
-      $list_definition->setClass($definition['list_class']);
-    }
-    else {
-      $type_definition = \Drupal::typedData()->getDefinition($definition['type']);
-      if (isset($type_definition['list_class'])) {
-        $list_definition->setClass($type_definition['list_class']);
-      }
-    }
-
-    // Take care of the item definition now.
-    // Required applies to the list definition only.
-    unset($definition['required']);
-    $item_definition = new DataDefinition($definition);
-    $list_definition->setItemDefinition($item_definition);
-    return $list_definition;
-  }
 }
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php
index 180003c..f3acbd3 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/Map.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\TypedData\Annotation\DataType;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\TypedData\TypedData;
 use Drupal\Core\TypedData\ComplexDataInterface;
 
@@ -49,9 +50,7 @@ class Map extends TypedData implements \IteratorAggregate, ComplexDataInterface
   public function getPropertyDefinitions() {
     $definitions = array();
     foreach ($this->values as $name => $value) {
-      $definitions[$name] = array(
-        'type' => 'any',
-      );
+      $definitions[$name] = DataDefinition::create('any');
     }
     return $definitions;
   }
@@ -63,7 +62,7 @@ public function getValue($include_computed = FALSE) {
     // Update the values and return them.
     foreach ($this->properties as $name => $property) {
       $definition = $property->getDefinition();
-      if ($include_computed || empty($definition['computed'])) {
+      if ($include_computed || !$definition->isComputed()) {
         $value = $property->getValue();
         // Only write NULL values if the whole map is not NULL.
         if (isset($this->values) || isset($value)) {
@@ -150,7 +149,7 @@ public function set($property_name, $value, $notify = TRUE) {
   public function getProperties($include_computed = FALSE) {
     $properties = array();
     foreach ($this->getPropertyDefinitions() as $name => $definition) {
-      if ($include_computed || empty($definition['computed'])) {
+      if ($include_computed || !$definition->isComputed()) {
         $properties[$name] = $this->get($name);
       }
     }
@@ -203,7 +202,7 @@ public function getPropertyDefinition($name) {
   public function isEmpty() {
     foreach ($this->properties as $property) {
       $definition = $property->getDefinition();
-      if (empty($definition['computed']) && $property->getValue() !== NULL) {
+      if (!$definition->isComputed() && $property->getValue() !== NULL) {
         return FALSE;
       }
     }
diff --git a/core/lib/Drupal/Core/TypedData/TypedData.php b/core/lib/Drupal/Core/TypedData/TypedData.php
index 6597f3c..12bec01 100644
--- a/core/lib/Drupal/Core/TypedData/TypedData.php
+++ b/core/lib/Drupal/Core/TypedData/TypedData.php
@@ -51,12 +51,8 @@
    *   root of a typed data tree. Defaults to NULL.
    *
    * @see \Drupal\Core\TypedData\TypedDataManager::create()
-   *
-   * @todo When \Drupal\Core\Config\TypedConfigManager has been fixed to use
-   *   class-based definitions, type-hint $definition to
-   *   DataDefinitionInterface.
    */
-  public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) {
+  public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
     $this->definition = $definition;
     $this->parent = $parent;
     $this->name = $name;
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
index 7e30812..8205ea1 100644
--- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php
+++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
@@ -94,7 +94,6 @@ public function createInstance($data_type, array $configuration) {
    * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
    *   The data definition of the typed data object. For backwards-compatibility
    *   an array representation of the data definition may be passed also.
-   *   @todo: Need to remove array support in https://drupal.org/node/2112239.
    * @param mixed $value
    *   (optional) The data value. If set, it has to match one of the supported
    *   data type format as documented for the data type classes.
@@ -120,11 +119,7 @@ public function createInstance($data_type, array $configuration) {
    * @see \Drupal\Core\TypedData\Plugin\DataType\Uri
    * @see \Drupal\Core\TypedData\Plugin\DataType\Binary
    */
-  public function create($definition, $value = NULL, $name = NULL, $parent = NULL) {
-    // @todo: Remove array support once https://drupal.org/node/2112239 is in.
-    if (is_array($definition)) {
-      $definition = DataDefinition::createFromOldStyleDefinition($definition);
-    }
+  public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL) {
     $typed_data = $this->createInstance($definition->getDataType(), array(
       'data_definition' => $definition,
       'name' => $name,
@@ -193,9 +188,9 @@ public function getInstance(array $options) {
    */
   public function getPropertyInstance(TypedDataInterface $object, $property_name, $value = NULL) {
     $definition = $object->getRoot()->getDefinition();
-    $key = $definition['type'];
-    if (isset($definition['settings'])) {
-      $key .= ':' . implode(',', $definition['settings']);
+    $key = $definition->getDataType();
+    if ($settings = $definition->getSettings()) {
+      $key .= ':' . implode(',', $settings);
     }
     $key .= ':' . $object->getPropertyPath() . '.';
     // If we are creating list items, we always use 0 in the key as all list
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
index ca99fa6..9d8990c 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Feed.php
@@ -8,6 +8,7 @@
 namespace Drupal\aggregator\Entity;
 
 use Drupal\Core\Entity\ContentEntityBase;
+use Drupal\Core\Field\FieldDefinition;
 use Symfony\Component\DependencyInjection\Container;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\Annotation\EntityType;
@@ -250,72 +251,65 @@ public function postSave(EntityStorageControllerInterface $storage_controller, $
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $fields['fid'] = array(
-      'label' => t('ID'),
-      'description' => t('The ID of the aggregor feed.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $fields['title'] = array(
-      'label' => t('Title'),
-      'description' => t('The title of the feed.'),
-      'type' => 'string_field',
-    );
-    $fields['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The feed language code.'),
-      'type' => 'language_field',
-    );
-    $fields['url'] = array(
-      'label' => t('URL'),
-      'description' => t('The URL to the feed.'),
-      'type' => 'uri_field',
-    );
-    $fields['refresh'] = array(
-      'label' => t('Refresh'),
-      'description' => t('How often to check for new feed items, in seconds.'),
-      'type' => 'integer_field',
-    );
-    $fields['checked'] = array(
-      'label' => t('Checked'),
-      'description' => t('Last time feed was checked for new items, as Unix timestamp.'),
-      'type' => 'integer_field',
-    );
-    $fields['queued'] = array(
-      'label' => t('Queued'),
-      'description' => t('Time when this feed was queued for refresh, 0 if not queued.'),
-      'type' => 'integer_field',
-    );
-    $fields['link'] = array(
-      'label' => t('Link'),
-      'description' => t('The link of the feed.'),
-      'type' => 'uri_field',
-    );
-    $fields['description'] = array(
-      'label' => t('Description'),
-      'description' => t("The parent website's description that comes from the !description element in the feed.", array('!description' => '')),
-      'type' => 'string_field',
-    );
-    $fields['image'] = array(
-      'label' => t('image'),
-      'description' => t('An image representing the feed.'),
-      'type' => 'uri_field',
-    );
-    $fields['hash'] = array(
-      'label' => t('Hash'),
-      'description' => t('Calculated hash of the feed data, used for validating cache.'),
-      'type' => 'string_field',
-    );
-    $fields['etag'] = array(
-      'label' => t('Etag'),
-      'description' => t('Entity tag HTTP response header, used for validating cache.'),
-      'type' => 'string_field',
-    );
-    $fields['modified'] = array(
-      'label' => t('Modified'),
-      'description' => t('When the feed was last modified, as a Unix timestamp.'),
-      'type' => 'integer_field',
-    );
+    $fields['fid'] = FieldDefinition::create('integer')
+      ->setLabel(t('Feed ID'))
+      ->setDescription(t('The ID of the aggregator feed.'))
+      ->setReadOnly(TRUE);
+
+    // @todo Why does this entity type not have an UUID field?
+
+    $fields['title'] = FieldDefinition::create('string')
+      ->setLabel(t('Title'))
+      ->setDescription(t('The title of the feed.'));
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The feed language code.'));
+
+    $fields['url'] = FieldDefinition::create('uri')
+      ->setLabel(t('URL'))
+      ->setDescription(t('The URL to the feed.'));
+
+    $fields['refresh'] = FieldDefinition::create('integer')
+      ->setLabel(t('Refresh'))
+      ->setDescription(t('How often to check for new feed items, in seconds.'));
+
+    // @todo Do we need a "timestamp" field? Not sure how DateItem is supposed
+    // to store its data.
+    $fields['checked'] = FieldDefinition::create('integer')
+      ->setLabel(t('Checked'))
+      ->setDescription(t('Last time feed was checked for new items, as Unix timestamp.'));
+
+    // @todo Candidate for timestamp.
+    $fields['queued'] = FieldDefinition::create('integer')
+      ->setLabel(t('Queued'))
+      ->setDescription(t('Time when this feed was queued for refresh, 0 if not queued.'));
+
+    $fields['link'] = FieldDefinition::create('uri')
+      ->setLabel(t('Link'))
+      ->setDescription(t('The link of the feed.'));
+
+    $fields['description'] = FieldDefinition::create('string')
+      ->setLabel(t('Description'))
+      ->setDescription(t("The parent website's description that comes from the !description element in the feed.", array('!description' => '')));
+
+    $fields['image'] = FieldDefinition::create('uri')
+      ->setLabel(t('Image'))
+      ->setDescription(t('An image representing the feed.'));
+
+    $fields['hash'] = FieldDefinition::create('string')
+      ->setLabel(t('Hash'))
+      ->setDescription(t('Calculated hash of the feed data, used for validating cache.'));
+
+    $fields['etag'] = FieldDefinition::create('string')
+      ->setLabel(t('Etag'))
+      ->setDescription(t('Entity tag HTTP response header, used for validating cache.'));
+
+    // @todo Candidate for timestamp.
+    $fields['modified'] = FieldDefinition::create('integer')
+      ->setLabel(t('Modified'))
+      ->setDescription(t('When the feed was last modified, as a Unix timestamp.'));
+
     return $fields;
   }
 
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php
index 3007200..a0366a5 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Entity/Item.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
 use Drupal\aggregator\ItemInterface;
+use Drupal\Core\Field\FieldDefinition;
 
 /**
  * Defines the aggregator item entity class.
@@ -80,52 +81,47 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $fields['iid'] = array(
-      'label' => t('ID'),
-      'description' => t('The ID of the aggregor item.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $fields['fid'] = array(
-      'label' => t('Aggregator feed ID'),
-      'description' => t('The ID of the aggregator feed.'),
-      'type' => 'integer_field',
-    );
-    $fields['title'] = array(
-      'label' => t('Title'),
-      'description' => t('The title of the feed item.'),
-      'type' => 'string_field',
-    );
-    $fields['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The feed item language code.'),
-      'type' => 'language_field',
-    );
-    $fields['link'] = array(
-      'label' => t('Link'),
-      'description' => t('The link of the feed item.'),
-      'type' => 'uri_field',
-    );
-    $fields['author'] = array(
-      'label' => t('Author'),
-      'description' => t('The author of the feed item.'),
-      'type' => 'string_field',
-    );
-    $fields['description'] = array(
-      'label' => t('Description'),
-      'description' => t('The body of the feed item.'),
-      'type' => 'string_field',
-    );
-    $fields['timestamp'] = array(
-      'label' => t('Posted timestamp'),
-      'description' => t('Posted date of the feed item, as a Unix timestamp.'),
-      'type' => 'integer_field',
-    );
-    $fields['guid'] = array(
-      'label' => t('GUID'),
-      'description' => t('Unique identifier for the feed item.'),
-      'type' => 'string_field',
-    );
+    $fields['iid'] = FieldDefinition::create('integer')
+      ->setLabel(t('Aggregator item ID'))
+      ->setDescription(t('The ID of the feed item.'))
+      ->setReadOnly(TRUE);
+
+    $fields['fid'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('Aggregator feed ID'))
+      ->setDescription(t('The ID of the aggregator feed.'))
+      ->setFieldSetting('target_type', 'aggregator_feed');
+
+    $fields['title'] = FieldDefinition::create('string')
+      ->setLabel(t('Title'))
+      ->setDescription(t('The title of the feed item.'));
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The feed item language code.'));
+
+    $fields['link'] = FieldDefinition::create('uri')
+      ->setLabel(t('Link'))
+      ->setDescription(t('The link of the feed item.'));
+
+    $fields['author'] = FieldDefinition::create('string')
+      ->setLabel(t('Author'))
+      ->setDescription(t('The author of the feed item.'));
+
+    // @todo Convert to a text field?
+    $fields['description'] = FieldDefinition::create('string')
+      ->setLabel(t('Description'))
+      ->setDescription(t('The body of the feed item.'));
+
+    // @todo Candidate for timestamp.
+    $fields['timestamp'] = FieldDefinition::create('integer')
+      ->setLabel(t('Posted timestamp'))
+      ->setDescription(t('Posted date of the feed item, as a Unix timestamp.'));
+
+    // @todo Why not a UUID field?
+    $fields['guid'] = FieldDefinition::create('string')
+      ->setLabel(t('GUID'))
+      ->setDescription(t('Unique identifier for the feed item.'));
+
     return $fields;
   }
 
@@ -133,7 +129,7 @@ public static function baseFieldDefinitions($entity_type) {
    * @inheritdoc
    */
   public function getFeedId() {
-    return $this->get('fid')->value;
+    return $this->get('fid')->target_id;
   }
 
   /**
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
index 055bfea..c254c0a 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\custom_block\CustomBlockInterface;
 
 /**
@@ -244,51 +245,44 @@ public function delete() {
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $properties['id'] = array(
-      'label' => t('ID'),
-      'description' => t('The custom block ID.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $properties['uuid'] = array(
-      'label' => t('UUID'),
-      'description' => t('The custom block UUID.'),
-      'type' => 'uuid_field',
-    );
-    $properties['revision_id'] = array(
-      'label' => t('Revision ID'),
-      'description' => t('The revision ID.'),
-      'type' => 'integer_field',
-    );
-    $properties['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The custom block language code.'),
-      'type' => 'language_field',
-    );
-    $properties['info'] = array(
-      'label' => t('Subject'),
-      'description' => t('The custom block name.'),
-      'type' => 'string_field',
-    );
-    $properties['type'] = array(
-      'label' => t('Block type'),
-      'description' => t('The block type.'),
-      'type' => 'string_field',
-    );
-    $properties['log'] = array(
-      'label' => t('Revision log message'),
-      'description' => t('The revision log message.'),
-      'type' => 'string_field',
-    );
-    $properties['changed'] = array(
-      'label' => t('Changed'),
-      'description' => t('The time that the custom block was last edited.'),
-      'type' => 'integer_field',
-      'property_constraints' => array(
-        'value' => array('EntityChanged' => array()),
-      ),
-    );
-    return $properties;
+    $fields['id'] = FieldDefinition::create('integer')
+      ->setLabel(t('Custom block ID'))
+      ->setDescription(t('The custom block ID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['uuid'] = FieldDefinition::create('uuid')
+      ->setLabel(t('UUID'))
+      ->setDescription(t('The custom block UUID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['revision_id'] = FieldDefinition::create('integer')
+      ->setLabel(t('Revision ID'))
+      ->setDescription(t('The revision ID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The custom block language code.'));
+
+    $fields['info'] = FieldDefinition::create('string')
+      ->setLabel(t('Subject'))
+      ->setDescription(t('The custom block name.'));
+
+    $fields['type'] = FieldDefinition::create('string')
+      ->setLabel(t('Block type'))
+      ->setDescription(t('The block type.'));
+
+    $fields['log'] = FieldDefinition::create('string')
+      ->setLabel(t('Revision log message'))
+      ->setDescription(t('The revision log message.'));
+
+    // @todo Candidate for timestamp.
+    $fields['changed'] = FieldDefinition::create('integer')
+      ->setLabel(t('Changed'))
+      ->setDescription(t('The time that the custom block was last edited.'))
+      ->setPropertyConstraints('value', array('EntityChanged' => array()));
+
+    return $fields;
   }
 
   /**
diff --git a/core/modules/comment/lib/Drupal/comment/CommentFieldName.php b/core/modules/comment/lib/Drupal/comment/CommentFieldName.php
index bb95d8a..7912fcc 100644
--- a/core/modules/comment/lib/Drupal/comment/CommentFieldName.php
+++ b/core/modules/comment/lib/Drupal/comment/CommentFieldName.php
@@ -8,6 +8,7 @@
 namespace Drupal\comment;
 
 use Drupal\Core\Field\Plugin\Field\FieldType\StringItem;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * The field item for the 'fieldname' field.
@@ -29,12 +30,10 @@ class CommentFieldName extends StringItem {
   public function getPropertyDefinitions() {
 
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'string',
-        'label' => t('String value'),
-        'class' => '\Drupal\comment\CommentFieldNameValue',
-        'computed' => TRUE,
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('string')
+        ->setLabel(t('String value'))
+        ->setClass('\Drupal\comment\CommentFieldNameValue')
+        ->setComputed(TRUE);
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
index cf96a59..1894bf3 100644
--- a/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
+++ b/core/modules/comment/lib/Drupal/comment/Entity/Comment.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\comment\CommentInterface;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Language\Language;
 
 /**
@@ -351,108 +352,95 @@ public function permalink() {
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $properties['cid'] = array(
-      'label' => t('ID'),
-      'description' => t('The comment ID.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $properties['uuid'] = array(
-      'label' => t('UUID'),
-      'description' => t('The comment UUID.'),
-      'type' => 'uuid_field',
-    );
-    $properties['pid'] = array(
-      'label' => t('Parent ID'),
-      'description' => t('The parent comment ID if this is a reply to a comment.'),
-      'type' => 'entity_reference_field',
-      'settings' => array('target_type' => 'comment'),
-    );
-    $properties['entity_id'] = array(
-      'label' => t('Entity ID'),
-      'description' => t('The ID of the entity of which this comment is a reply.'),
-      'type' => 'entity_reference_field',
-      'settings' => array('target_type' => 'node'),
-      'required' => TRUE,
-    );
-    $properties['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The comment language code.'),
-      'type' => 'language_field',
-    );
-    $properties['subject'] = array(
-      'label' => t('Subject'),
-      'description' => t('The comment title or subject.'),
-      'type' => 'string_field',
-    );
-    $properties['uid'] = array(
-      'label' => t('User ID'),
-      'description' => t('The user ID of the comment author.'),
-      'type' => 'entity_reference_field',
-      'settings' => array(
+    $fields['cid'] = FieldDefinition::create('integer')
+      ->setLabel(t('Comment ID'))
+      ->setDescription(t('The comment ID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['uuid'] = FieldDefinition::create('uuid')
+      ->setLabel(t('UUID'))
+      ->setDescription(t('The comment UUID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['pid'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('Parent ID'))
+      ->setDescription(t('The parent comment ID if this is a reply to a comment.'))
+      ->setFieldSetting('target_type', 'comment');
+
+    $fields['entity_id'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('Entity ID'))
+      ->setDescription(t('The ID of the entity of which this comment is a reply.'))
+      ->setFieldSetting('target_type', 'node')
+      ->setRequired(TRUE);
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The comment language code.'));
+
+    $fields['subject'] = FieldDefinition::create('string')
+      ->setLabel(t('Subject'))
+      ->setDescription(t('The comment title or subject.'));
+
+    $fields['uid'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('User ID'))
+      ->setDescription(t('The user ID of the comment author.'))
+      ->setFieldSettings(array(
         'target_type' => 'user',
         'default_value' => 0,
-      ),
-    );
-    $properties['name'] = array(
-      'label' => t('Name'),
-      'description' => t("The comment author's name."),
-      'type' => 'string_field',
-      'settings' => array('default_value' => ''),
-    );
-    $properties['mail'] = array(
-      'label' => t('e-mail'),
-      'description' => t("The comment author's e-mail address."),
-      'type' => 'string_field',
-    );
-    $properties['homepage'] = array(
-      'label' => t('Homepage'),
-      'description' => t("The comment author's home page address."),
-      'type' => 'string_field',
-    );
-    $properties['hostname'] = array(
-      'label' => t('Hostname'),
-      'description' => t("The comment author's hostname."),
-      'type' => 'string_field',
-    );
-    $properties['created'] = array(
-      'label' => t('Created'),
-      'description' => t('The time that the comment was created.'),
-      'type' => 'integer_field',
-    );
-    $properties['changed'] = array(
-      'label' => t('Changed'),
-      'description' => t('The time that the comment was last edited.'),
-      'type' => 'integer_field',
-    );
-    $properties['status'] = array(
-      'label' => t('Publishing status'),
-      'description' => t('A boolean indicating whether the comment is published.'),
-      'type' => 'boolean_field',
-    );
-    $properties['thread'] = array(
-      'label' => t('Thread place'),
-      'description' => t("The alphadecimal representation of the comment's place in a thread, consisting of a base 36 string prefixed by an integer indicating its length."),
-      'type' => 'string_field',
-    );
-    $properties['entity_type'] = array(
-      'label' => t('Entity type'),
-      'description' => t("The entity type to which this comment is attached."),
-      'type' => 'string_field',
-    );
-    $properties['field_id'] = array(
-      'label' => t('Field ID'),
-      'description' => t("The comment field id."),
-      'type' => 'string_field',
-    );
-    $properties['field_name'] = array(
-      'label' => t('Comment field name'),
-      'description' => t("The field name through which this comment was added."),
-      'type' => 'string_field',
-      'computed' => TRUE,
-      'class' => '\Drupal\comment\CommentFieldName',
-    );
-    return $properties;
+      ));
+
+    $fields['name'] = FieldDefinition::create('string')
+      ->setLabel(t('Name'))
+      ->setDescription(t("The comment author's name."))
+      ->setFieldSetting('default_value', '');
+
+    $fields['mail'] = FieldDefinition::create('email')
+      ->setLabel(t('Email'))
+      ->setDescription(t("The comment author's e-mail address."));
+
+    $fields['homepage'] = FieldDefinition::create('string')
+      ->setLabel(t('Homepage'))
+      ->setDescription(t("The comment author's home page address."));
+
+    $fields['hostname'] = FieldDefinition::create('string')
+      ->setLabel(t('Hostname'))
+      ->setDescription(t("The comment author's hostname."));
+
+    // @todo Candidate for timestamp.
+    $fields['created'] = FieldDefinition::create('integer')
+      ->setLabel(t('Created'))
+      ->setDescription(t('The time that the comment was created.'));
+
+    // @todo Candidate for timestamp.
+    $fields['changed'] = FieldDefinition::create('integer')
+      ->setLabel(t('Changed'))
+      ->setDescription(t('The time that the comment was last edited.'))
+      ->setPropertyConstraints('value', array('EntityChanged' => array()));
+
+    $fields['status'] = FieldDefinition::create('boolean')
+      ->setLabel(t('Publishing status'))
+      ->setDescription(t('A boolean indicating whether the comment is published.'));
+
+    $fields['thread'] = FieldDefinition::create('string')
+      ->setLabel(t('Thread place'))
+      ->setDescription(t("The alphadecimal representation of the comment's place in a thread, consisting of a base 36 string prefixed by an integer indicating its length."));
+
+    $fields['entity_type'] = FieldDefinition::create('string')
+      ->setLabel(t('Entity type'))
+      ->setDescription(t('The entity type to which this comment is attached.'));
+
+    // @todo Change to an entity_reference field?
+    $fields['field_id'] = FieldDefinition::create('string')
+      ->setLabel(t('Field ID'))
+      ->setDescription(t('The comment field id.'));
+
+    $fields['field_name'] = FieldDefinition::create('string')
+      ->setLabel(t('Comment field name'))
+      ->setDescription(t('The field name through which this comment was added.'))
+      ->setComputed(TRUE)
+      ->setClass('\Drupal\comment\CommentFieldName');
+
+    return $fields;
   }
 
   /**
diff --git a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
index c91f1bb..7a73293 100644
--- a/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
+++ b/core/modules/comment/lib/Drupal/comment/Plugin/Field/FieldType/CommentItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\comment\Plugin\Field\FieldType;
 
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 use Drupal\Core\Field\ConfigFieldItemBase;
 
@@ -43,35 +44,26 @@ class CommentItem extends ConfigFieldItemBase {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions = array(
-        'status' => array(
-          'type' => 'integer',
-          'label' => t('Comment status value'),
-        ),
-        'cid' => array(
-          'type' => 'integer',
-          'label' => t('Last comment ID'),
-        ),
-        'last_comment_timestamp' => array(
-          'label' => t('Last comment timestamp'),
-          'description' => t('The time that the last comment was created.'),
-          'type' => 'integer',
-        ),
-        'last_comment_name' => array(
-          'label' => t('Last comment name'),
-          'description' => t('The name of the user posting the last comment.'),
-          'type' => 'string',
-        ),
-        'last_comment_uid' => array(
-          'type' => 'integer',
-          'label' => t('Last comment user ID'),
-        ),
-        'comment_count' => array(
-          'label' => t('Number of comments'),
-          'description' => t('The number of comments.'),
-          'type' => 'integer',
-        ),
-      );
+      static::$propertyDefinitions['status'] = DataDefinition::create('integer')
+        ->setLabel(t('Comment status value'));
+
+      static::$propertyDefinitions['cid'] = DataDefinition::create('integer')
+        ->setLabel(t('Last comment ID'));
+
+      static::$propertyDefinitions['last_comment_timestamp'] = DataDefinition::create('integer')
+        ->setLabel(t('Last comment timestamp'))
+        ->setDescription(t('The time that the last comment was created.'));
+
+      static::$propertyDefinitions['last_comment_name'] = DataDefinition::create('integer')
+        ->setLabel(t('Last comment name'))
+        ->setDescription(t('The name of the user posting the last comment.'));
+
+      static::$propertyDefinitions['last_comment_uid'] = DataDefinition::create('integer')
+        ->setLabel(t('Last comment user ID'));
+
+      static::$propertyDefinitions['comment_count'] = DataDefinition::create('integer')
+        ->setLabel(t('Number of comments'))
+        ->setDescription(t('The number of comments.'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/contact/lib/Drupal/contact/Entity/Message.php b/core/modules/contact/lib/Drupal/contact/Entity/Message.php
index aaaa64e..8460fb6 100644
--- a/core/modules/contact/lib/Drupal/contact/Entity/Message.php
+++ b/core/modules/contact/lib/Drupal/contact/Entity/Message.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\contact\MessageInterface;
+use Drupal\Core\Field\FieldDefinition;
 
 /**
  * Defines the contact message entity.
@@ -142,44 +143,37 @@ public function getPersonalRecipient() {
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $fields['category'] = array(
-      'label' => t('Category ID'),
-      'description' => t('The ID of the associated category.'),
-      'type' => 'entity_reference_field',
-      'settings' => array('target_type' => 'contact_category'),
-      'required' => TRUE,
-    );
-    $fields['name'] = array(
-      'label' => t("The sender's name"),
-      'description' => t('The name of the person that is sending the contact message.'),
-      'type' => 'string_field',
-    );
-    $fields['mail'] = array(
-      'label' => t("The sender's e-mail"),
-      'description' => t('The e-mail of the person that is sending the contact message.'),
-      'type' => 'email_field',
-    );
-    $fields['subject'] = array(
-      'label' => t('The message subject'),
-      'description' => t('The subject of the contact message.'),
-      'type' => 'string_field',
-    );
-    $fields['message'] = array(
-      'label' => t('The message text'),
-      'description' => t('The text of the contact message.'),
-      'type' => 'string_field',
-    );
-    $fields['copy'] = array(
-      'label' => t('Copy'),
-      'description' => t('Whether to send a copy of the message to the sender.'),
-      'type' => 'boolean_field',
-    );
-    $fields['recipient'] = array(
-      'label' => t('Recipient ID'),
-      'description' => t('The ID of the recipient user for personal contact messages.'),
-      'type' => 'entity_reference_field',
-      'settings' => array('target_type' => 'user'),
-    );
+    $fields['category'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('Category ID'))
+      ->setDescription(t('The ID of the associated category.'))
+      ->setFieldSettings(array('target_type' => 'contact_category'))
+      ->setRequired(TRUE);
+
+    $fields['name'] = FieldDefinition::create('string')
+      ->setLabel(t("The sender's name"))
+      ->setDescription(t('The name of the person that is sending the contact message.'));
+
+    $fields['mail'] = FieldDefinition::create('email')
+      ->setLabel(t("The sender's email"))
+      ->setDescription(t('The email of the person that is sending the contact message.'));
+
+    $fields['subject'] = FieldDefinition::create('string')
+      ->setLabel(t('The message subject'))
+      ->setDescription(t('The subject of the contact message.'));
+
+    $fields['message'] = FieldDefinition::create('string')
+      ->setLabel(t('The message text'))
+      ->setDescription(t('The text of the contact message.'));
+
+    $fields['copy'] = FieldDefinition::create('boolean')
+      ->setLabel(t('Copy'))
+      ->setDescription(t('Whether to send a copy of the message to the sender.'));
+
+    $fields['recipient'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('Recipient ID'))
+      ->setDescription(t('The ID of the recipient user for personal contact messages.'))
+      ->setFieldSettings(array('target_type' => 'user'));
+
     return $fields;
   }
 
diff --git a/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php b/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php
index d6954b9..c7fdd29 100644
--- a/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php
+++ b/core/modules/datetime/lib/Drupal/datetime/DateTimeComputed.php
@@ -8,6 +8,7 @@
 namespace Drupal\datetime;
 
 use Drupal\Core\Datetime\DrupalDateTime;
+use Drupal\Core\TypedData\DataDefinitionInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 use Drupal\Core\TypedData\TypedData;
 
@@ -29,7 +30,7 @@ class DateTimeComputed extends TypedData {
   /**
    * {@inheritdoc}
    */
-  public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) {
+  public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
     parent::__construct($definition, $name, $parent);
     if (!isset($definition['settings']['date source'])) {
       throw new \InvalidArgumentException("The definition's 'date source' key has to specify the name of the date property to be computed.");
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
index e4cad9a..5efae7f 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/Field/FieldType/DateTimeItem.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\Core\Field\PrepareCacheInterface;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 use Drupal\Core\Field\ConfigFieldItemBase;
 
@@ -43,20 +44,17 @@ class DateTimeItem extends ConfigFieldItemBase implements PrepareCacheInterface
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'datetime_iso8601',
-        'label' => t('Date value'),
-      );
-      static::$propertyDefinitions['date'] = array(
-        'type' => 'datetime_computed',
-        'label' => t('Computed date'),
-        'description' => t('The computed DateTime object.'),
-        'computed' => TRUE,
-        'class' => '\Drupal\datetime\DateTimeComputed',
-        'settings' => array(
+      static::$propertyDefinitions['value'] = DataDefinition::create('datetime_iso8601')
+        ->setLabel(t('Date value'));
+
+      static::$propertyDefinitions['date'] = DataDefinition::create('datetime_computed')
+        ->setLabel(t('Computed date'))
+        ->setDescription(t('The computed DateTime object.'))
+        ->setComputed(TRUE)
+        ->setClass('\Drupal\datetime\DateTimeComputed')
+        ->setSettings(array(
           'date source' => 'value',
-        ),
-      );
+        ));
     }
 
     return static::$propertyDefinitions;
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php
index 47f04c6..e7b1cb3 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/HiddenTestItem.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\Annotation\FieldType;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field_test\Plugin\Field\FieldType\TestItem;
 
 /**
@@ -38,12 +39,9 @@ class HiddenTestItem extends TestItem {
    * Implements \Drupal\Core\TypedData\ComplexDataInterface::getPropertyDefinitions().
    */
   public function getPropertyDefinitions() {
-
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'integer',
-        'label' => t('Test integer value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('integer')
+        ->setLabel(t('Test integer value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php
index 32dedba..a32dfa4 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/ShapeItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\field_test\Plugin\Field\FieldType;
 
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 use Drupal\Core\Field\ConfigFieldItemBase;
 
@@ -39,16 +40,12 @@ class ShapeItem extends ConfigFieldItemBase {
    * {@inheritdoc}
    */
   public function getPropertyDefinitions() {
-
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['shape'] = array(
-        'type' => 'string',
-        'label' => t('Shape'),
-      );
-      static::$propertyDefinitions['color'] = array(
-        'type' => 'string',
-        'label' => t('Color'),
-      );
+      static::$propertyDefinitions['shape'] = DataDefinition::create('string')
+        ->setLabel(t('Shape'));
+
+      static::$propertyDefinitions['color'] = DataDefinition::create('string')
+        ->setLabel(t('Color'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
index 79ac618..a92f517 100644
--- a/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
+++ b/core/modules/field/tests/modules/field_test/lib/Drupal/field_test/Plugin/Field/FieldType/TestItem.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\Annotation\FieldType;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Field\PrepareCacheInterface;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 use Drupal\Core\Field\ConfigFieldItemBase;
 
@@ -48,12 +49,9 @@ class TestItem extends ConfigFieldItemBase implements PrepareCacheInterface {
    * {@inheritdoc}
    */
   public function getPropertyDefinitions() {
-
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'integer',
-        'label' => t('Test integer value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('integer')
+        ->setLabel(t('Test integer value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/file/lib/Drupal/file/Entity/File.php b/core/modules/file/lib/Drupal/file/Entity/File.php
index 57b8105..0638cae 100644
--- a/core/modules/file/lib/Drupal/file/Entity/File.php
+++ b/core/modules/file/lib/Drupal/file/Entity/File.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Language\Language;
 use Drupal\file\FileInterface;
 use Drupal\user\UserInterface;
@@ -215,60 +216,51 @@ public static function preDelete(EntityStorageControllerInterface $storage_contr
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $properties['fid'] = array(
-      'label' => t('File ID'),
-      'description' => t('The file ID.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $properties['uuid'] = array(
-      'label' => t('UUID'),
-      'description' => t('The file UUID.'),
-      'type' => 'uuid_field',
-      'read-only' => TRUE,
-    );
-    $properties['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The file language code.'),
-      'type' => 'language_field',
-    );
-    $properties['uid'] = array(
-      'label' => t('User ID'),
-      'description' => t('The user ID of the file.'),
-      'type' => 'entity_reference_field',
-      'settings' => array('target_type' => 'user'),
-    );
-    $properties['filename'] = array(
-      'label' => t('Filename'),
-      'description' => t('Name of the file with no path components.'),
-      'type' => 'string_field',
-    );
-    $properties['uri'] = array(
-      'label' => t('URI'),
-      'description' => t('The URI to access the file (either local or remote).'),
-      'type' => 'string_field',
-    );
-    $properties['filemime'] = array(
-      'label' => t('File MIME type'),
-      'description' => t("The file's MIME type."),
-      'type' => 'string_field',
-    );
-    $properties['filesize'] = array(
-      'label' => t('File size'),
-      'description' => t('The size of the file in bytes.'),
-      'type' => 'boolean_field',
-    );
-    $properties['status'] = array(
-      'label' => t('Status'),
-      'description' => t('The status of the file, temporary (0) and permanent (1)'),
-      'type' => 'integer_field',
-    );
-    $properties['timestamp'] = array(
-      'label' => t('Created'),
-      'description' => t('The time that the node was created.'),
-      'type' => 'integer_field',
-    );
-    return $properties;
+    $fields['fid'] = FieldDefinition::create('integer')
+      ->setLabel(t('File ID'))
+      ->setDescription(t('The file ID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['uuid'] = FieldDefinition::create('uuid')
+      ->setLabel(t('UUID'))
+      ->setDescription(t('The file UUID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The file language code.'));
+
+    $fields['uid'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('User ID'))
+      ->setDescription(t('The user ID of the file.'))
+      ->setFieldSetting('target_type', 'user');
+
+    $fields['filename'] = FieldDefinition::create('string')
+      ->setLabel(t('Filename'))
+      ->setDescription(t('Name of the file with no path components.'));
+
+    $fields['uri'] = FieldDefinition::create('uri')
+      ->setLabel(t('URI'))
+      ->setDescription(t('The URI to access the file (either local or remote).'));
+
+    $fields['filemime'] = FieldDefinition::create('string')
+      ->setLabel(t('File MIME type'))
+      ->setDescription(t("The file's MIME type."));
+
+    // @todo In what world does it make sense for a 'filesize' property to be a boolean field?
+    $fields['filesize'] = FieldDefinition::create('boolean')
+      ->setLabel(t('File size'))
+      ->setDescription(t('The size of the file in bytes.'));
+
+    $fields['status'] = FieldDefinition::create('integer')
+      ->setLabel(t('Status'))
+      ->setDescription(t('The status of the file, temporary (0) and permanent (1).'));
+
+    $fields['timestamp'] = FieldDefinition::create('integer')
+      ->setLabel(t('Created'))
+      ->setDescription(t('The time that the node was created.'));
+
+    return $fields;
   }
 
 }
diff --git a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
index 2173689..f627604 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/Field/FieldType/FileItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\file\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 use Drupal\Core\Field\ConfigFieldItemInterface;
 
@@ -87,19 +88,16 @@ public static function schema(FieldInterface $field) {
    * {@inheritdoc}
    */
   public function getPropertyDefinitions() {
-    $this->definition['settings']['target_type'] = 'file';
+    $this->definition->getSettings(array('target_type' => 'file'));
 
     if (!isset(static::$propertyDefinitions)) {
       static::$propertyDefinitions = parent::getPropertyDefinitions();
 
-      static::$propertyDefinitions['display'] = array(
-        'type' => 'boolean',
-        'label' => t('Flag to control whether this file should be displayed when viewing content.'),
-      );
-      static::$propertyDefinitions['description'] = array(
-        'type' => 'string',
-        'label' => t('A description of the file.'),
-      );
+      static::$propertyDefinitions['display'] = DataDefinition::create('boolean')
+        ->setLabel(t('Flag to control whether this file should be displayed when viewing content'));
+
+      static::$propertyDefinitions['description'] = DataDefinition::create('string')
+        ->setLabel(t('A description of the file'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
index b697465..acf1dd6 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/Field/FieldType/ImageItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\image\Plugin\Field\FieldType;
 
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 use Drupal\file\Plugin\Field\FieldType\FileItem;
 
@@ -117,27 +118,22 @@ public static function schema(FieldInterface $field) {
    * {@inheritdoc}
    */
   public function getPropertyDefinitions() {
-    $this->definition['settings']['target_type'] = 'file';
+    $this->definition->getSettings(array('target_type' => 'file'));
 
     if (!isset(static::$propertyDefinitions)) {
       static::$propertyDefinitions = parent::getPropertyDefinitions();
 
-      static::$propertyDefinitions['alt'] = array(
-        'type' => 'string',
-        'label' => t("Alternative image text, for the image's 'alt' attribute."),
-      );
-      static::$propertyDefinitions['title'] = array(
-        'type' => 'string',
-        'label' => t("Image title text, for the image's 'title' attribute."),
-      );
-      static::$propertyDefinitions['width'] = array(
-        'type' => 'integer',
-        'label' => t('The width of the image in pixels.'),
-      );
-      static::$propertyDefinitions['height'] = array(
-        'type' => 'integer',
-        'label' => t('The height of the image in pixels.'),
-      );
+      static::$propertyDefinitions['alt'] = DataDefinition::create('string')
+        ->setLabel(t("Alternative image text, for the image's 'alt' attribute."));
+
+      static::$propertyDefinitions['title'] = DataDefinition::create('string')
+        ->setLabel(t("Image title text, for the image's 'title' attribute."));
+
+      static::$propertyDefinitions['width'] = DataDefinition::create('integer')
+        ->setLabel(t('The width of the image in pixels.'));
+
+      static::$propertyDefinitions['height'] = DataDefinition::create('integer')
+        ->setLabel(t('The height of the image in pixels.'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
index 55fcc38..edd2d96 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/Field/FieldType/LinkItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\link\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\ConfigFieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 
 /**
@@ -38,18 +39,14 @@ class LinkItem extends ConfigFieldItemBase {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['url'] = array(
-        'type' => 'uri',
-        'label' => t('URL'),
-      );
-      static::$propertyDefinitions['title'] = array(
-        'type' => 'string',
-        'label' => t('Link text'),
-      );
-      static::$propertyDefinitions['attributes'] = array(
-        'type' => 'map',
-        'label' => t('Attributes'),
-      );
+      static::$propertyDefinitions['url'] = DataDefinition::create('uri')
+        ->setLabel(t('URL'));
+
+      static::$propertyDefinitions['title'] = DataDefinition::create('string')
+        ->setLabel(t('Link text'));
+
+      static::$propertyDefinitions['attributes'] = DataDefinition::create('map')
+        ->setLabel(t('Attributes'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
index 7be07a9..e2dd5a7 100644
--- a/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
+++ b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
@@ -7,8 +7,8 @@
 
 namespace Drupal\locale;
 
-use Drupal\Core\Language\Language;
 use Drupal\Core\TypedData\ContextAwareInterface;
+use Drupal\Core\TypedData\DataDefinitionInterface;
 use Drupal\Core\Config\Schema\Element;
 use Drupal\Core\Config\Schema\ArrayElement;
 
@@ -50,7 +50,7 @@ class LocaleTypedConfig extends Element {
    * @param \Drupal\locale\LocaleConfigManager $localeConfig;
    *   The locale configuration manager object.
    */
-  public function __construct($definition, $name, $langcode, \Drupal\locale\LocaleConfigManager $localeConfig) {
+  public function __construct(DataDefinitionInterface $definition, $name, $langcode, LocaleConfigManager $localeConfig) {
     parent::__construct($definition, $name);
     $this->langcode = $langcode;
     $this->localeConfig = $localeConfig;
diff --git a/core/modules/node/lib/Drupal/node/Entity/Node.php b/core/modules/node/lib/Drupal/node/Entity/Node.php
index 3700499..a7311a3 100644
--- a/core/modules/node/lib/Drupal/node/Entity/Node.php
+++ b/core/modules/node/lib/Drupal/node/Entity/Node.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\node\NodeInterface;
@@ -327,104 +328,87 @@ public function setRevisionAuthorId($uid) {
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $properties['nid'] = array(
-      'label' => t('Node ID'),
-      'description' => t('The node ID.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $properties['uuid'] = array(
-      'label' => t('UUID'),
-      'description' => t('The node UUID.'),
-      'type' => 'uuid_field',
-      'read-only' => TRUE,
-    );
-    $properties['vid'] = array(
-      'label' => t('Revision ID'),
-      'description' => t('The node revision ID.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $properties['type'] = array(
-      'label' => t('Type'),
-      'description' => t('The node type.'),
-      'type' => 'string_field',
-      'read-only' => TRUE,
-    );
-    $properties['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The node language code.'),
-      'type' => 'language_field',
-    );
-    $properties['title'] = array(
-      'label' => t('Title'),
-      'description' => t('The title of this node, always treated as non-markup plain text.'),
-      'type' => 'string_field',
-      'required' => TRUE,
-      'settings' => array(
-        'default_value' => '',
-      ),
-      'property_constraints' => array(
-        'value' => array('Length' => array('max' => 255)),
-      ),
-      'translatable' => TRUE,
-    );
-    $properties['uid'] = array(
-      'label' => t('User ID'),
-      'description' => t('The user ID of the node author.'),
-      'type' => 'entity_reference_field',
-      'settings' => array(
+    $fields['nid'] = FieldDefinition::create('integer')
+      ->setLabel(t('Node ID'))
+      ->setDescription(t('The node ID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['uuid'] = FieldDefinition::create('uuid')
+      ->setLabel(t('UUID'))
+      ->setDescription(t('The node UUID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['vid'] = FieldDefinition::create('integer')
+      ->setLabel(t('Revision ID'))
+      ->setDescription(t('The node revision ID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['type'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('Type'))
+      ->setDescription(t('The node type.'))
+      ->setFieldSetting('target_type', 'node_type')
+      ->setReadOnly(TRUE);
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The node language code.'));
+
+    $fields['title'] = FieldDefinition::create('string')
+      ->setLabel(t('Title'))
+      ->setDescription(t('The title of this node, always treated as non-markup plain text.'))
+      ->setRequired(TRUE)
+      ->setFieldSetting('default_value', '')
+      ->setPropertyConstraints('value', array('Length' => array('max' => 255)))
+      ->setTranslatable(TRUE);
+
+    $fields['uid'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('User ID'))
+      ->setDescription(t('The user ID of the node author.'))
+      ->setFieldSettings(array(
         'target_type' => 'user',
         'default_value' => 0,
-      ),
-    );
-    $properties['status'] = array(
-      'label' => t('Publishing status'),
-      'description' => t('A boolean indicating whether the node is published.'),
-      'type' => 'boolean_field',
-    );
-    $properties['created'] = array(
-      'label' => t('Created'),
-      'description' => t('The time that the node was created.'),
-      'type' => 'integer_field',
-    );
-    $properties['changed'] = array(
-      'label' => t('Changed'),
-      'description' => t('The time that the node was last edited.'),
-      'type' => 'integer_field',
-      'property_constraints' => array(
-        'value' => array('EntityChanged' => array()),
-      ),
-    );
-    $properties['promote'] = array(
-      'label' => t('Promote'),
-      'description' => t('A boolean indicating whether the node should be displayed on the front page.'),
-      'type' => 'boolean_field',
-    );
-    $properties['sticky'] = array(
-      'label' => t('Sticky'),
-      'description' => t('A boolean indicating whether the node should be displayed at the top of lists in which it appears.'),
-      'type' => 'boolean_field',
-    );
-    $properties['revision_timestamp'] = array(
-      'label' => t('Revision timestamp'),
-      'description' => t('The time that the current revision was created.'),
-      'type' => 'integer_field',
-      'queryable' => FALSE,
-    );
-    $properties['revision_uid'] = array(
-      'label' => t('Revision user ID'),
-      'description' => t('The user ID of the author of the current revision.'),
-      'type' => 'entity_reference_field',
-      'settings' => array('target_type' => 'user'),
-      'queryable' => FALSE,
-    );
-    $properties['log'] = array(
-      'label' => t('Log'),
-      'description' => t('The log entry explaining the changes in this version.'),
-      'type' => 'string_field',
-    );
-    return $properties;
+      ));
+
+    $fields['status'] = FieldDefinition::create('boolean')
+      ->setLabel(t('Publishing status'))
+      ->setDescription(t('A boolean indicating whether the node is published.'));
+
+    // @todo Candidate for timestamp.
+    $fields['created'] = FieldDefinition::create('integer')
+      ->setLabel(t('Created'))
+      ->setDescription(t('The time that the node was created.'));
+
+    // @todo Candidate for timestamp.
+    $fields['changed'] = FieldDefinition::create('integer')
+      ->setLabel(t('Changed'))
+      ->setDescription(t('The time that the node was last edited.'))
+      ->setPropertyConstraints('value', array('EntityChanged' => array()));
+
+    $fields['promote'] = FieldDefinition::create('boolean')
+      ->setLabel(t('Promote'))
+      ->setDescription(t('A boolean indicating whether the node should be displayed on the front page.'));
+
+    $fields['sticky'] = FieldDefinition::create('boolean')
+      ->setLabel(t('Sticky'))
+      ->setDescription(t('A boolean indicating whether the node should be displayed at the top of lists in which it appears.'));
+
+    // @todo Candidate for timestamp.
+    $fields['revision_timestamp'] = FieldDefinition::create('integer')
+      ->setLabel(t('Revision timestamp'))
+      ->setDescription(t('The time that the current revision was created.'))
+      ->setFieldQueryable(FALSE);
+
+    $fields['revision_uid'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('Revision user ID'))
+      ->setDescription(t('The user ID of the author of the current revision.'))
+      ->setFieldSettings(array('target_type' => 'user'))
+      ->setFieldQueryable(FALSE);
+
+    $fields['log'] = FieldDefinition::create('string')
+      ->setLabel(t('Log'))
+      ->setDescription(t('The log entry explaining the changes in this revision.'));
+
+    return $fields;
   }
 
 }
diff --git a/core/modules/node/tests/modules/node_access_test/node_access_test.module b/core/modules/node/tests/modules/node_access_test/node_access_test.module
index 923bcb0..12800b1 100644
--- a/core/modules/node/tests/modules/node_access_test/node_access_test.module
+++ b/core/modules/node/tests/modules/node_access_test/node_access_test.module
@@ -10,6 +10,7 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\node\NodeInterface;
 
 /**
@@ -82,12 +83,10 @@ function node_access_test_permission() {
  */
 function node_access_test_entity_field_info($entity_type) {
   if ($entity_type === 'node') {
-    $info['definitions']['private'] = array(
-      'type' => 'field_item:boolean',
-      'label' => t('Private'),
-      'computed' => TRUE,
-      'list' => TRUE,
-    );
+      $info['definitions']['private'] = FieldDefinition::create('boolean')
+        ->setLabel(t('Private'))
+        ->setComputed(TRUE);
+
     return $info;
   }
 }
diff --git a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php
index 6dbb3c4..16353db 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/DecimalItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\number\Plugin\Field\FieldType;
 
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 use Drupal\Component\Utility\MapArray;
 
@@ -38,10 +39,8 @@ class DecimalItem extends NumberItemBase {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'string',
-        'label' => t('Decimal value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('string')
+        ->setLabel(t('Decimal value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php
index 3a58097..88ee07f 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/FloatItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\number\Plugin\Field\FieldType;
 
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 
 /**
@@ -33,10 +34,8 @@ class FloatItem extends NumberItemBase {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'float',
-        'label' => t('float value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('float')
+        ->setLabel(t('Float value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php
index 52954df..dfe35f6 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/Field/FieldType/IntegerItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\number\Plugin\Field\FieldType;
 
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 
 /**
@@ -33,10 +34,8 @@ class IntegerItem extends NumberItemBase {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'integer',
-        'label' => t('Integer value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('integer')
+        ->setLabel(t('Integer value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php b/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php
index 3050b92..6b18833 100644
--- a/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php
+++ b/core/modules/options/lib/Drupal/options/Type/ListFloatItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\options\Type;
 
 use Drupal\Core\Field\Plugin\Field\FieldType\LegacyConfigFieldItem;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'list_float' entity field item.
@@ -29,10 +30,8 @@ class ListFloatItem extends LegacyConfigFieldItem {
   public function getPropertyDefinitions() {
 
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'float',
-        'label' => t('Float value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('float')
+        ->setLabel(t('Float value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php b/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php
index b9d6f55..72ed788 100644
--- a/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php
+++ b/core/modules/options/lib/Drupal/options/Type/ListIntegerItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\options\Type;
 
 use Drupal\Core\Field\Plugin\Field\FieldType\LegacyConfigFieldItem;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'list_integer' entity field item.
@@ -29,10 +30,8 @@ class ListIntegerItem extends LegacyConfigFieldItem {
   public function getPropertyDefinitions() {
 
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'integer',
-        'label' => t('Integer value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('integer')
+        ->setLabel(t('Integer value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/options/lib/Drupal/options/Type/ListTextItem.php b/core/modules/options/lib/Drupal/options/Type/ListTextItem.php
index f3753db..b66d355 100644
--- a/core/modules/options/lib/Drupal/options/Type/ListTextItem.php
+++ b/core/modules/options/lib/Drupal/options/Type/ListTextItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\options\Type;
 
 use Drupal\Core\Field\Plugin\Field\FieldType\LegacyConfigFieldItem;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'list_text' configurable field type.
@@ -29,10 +30,8 @@ class ListTextItem extends LegacyConfigFieldItem {
   public function getPropertyDefinitions() {
 
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'string',
-        'label' => t('Text value'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('string')
+        ->setLabel(t('Text value'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php
index 1b0ce50..601bc0b 100644
--- a/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php
+++ b/core/modules/path/lib/Drupal/path/Plugin/Field/FieldType/PathItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\path\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Defines the 'path' entity field type.
@@ -35,14 +36,11 @@ class PathItem extends FieldItemBase {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['alias'] = array(
-        'type' => 'string',
-        'label' => t('Path alias'),
-      );
-      static::$propertyDefinitions['pid'] = array(
-        'type' => 'integer',
-        'label' => t('Path id'),
-      );
+      static::$propertyDefinitions['alias'] = DataDefinition::create('string')
+        ->setLabel(t('Path alias'));
+
+      static::$propertyDefinitions['pid'] = DataDefinition::create('string')
+        ->setLabel(t('Path id'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/path/path.module b/core/modules/path/path.module
index d33f881..e638eb9 100644
--- a/core/modules/path/path.module
+++ b/core/modules/path/path.module
@@ -8,6 +8,7 @@
 use Drupal\Core\Language\Language;
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\Core\Field\FieldDefinition;
 
 /**
  * Implements hook_help().
@@ -211,12 +212,10 @@ function path_form_taxonomy_term_form_alter(&$form, $form_state) {
  */
 function path_entity_field_info($entity_type) {
   if ($entity_type === 'taxonomy_term' || $entity_type === 'node') {
-    $info['definitions']['path'] = array(
-      'type' => 'field_item:path',
-      'label' => t('The path alias'),
-      'computed' => TRUE,
-      'list' => TRUE,
-    );
+    $info['definitions']['path'] = FieldDefinition::create('path')
+      ->setLabel(t('The path alias'))
+      ->setComputed(TRUE);
+
     return $info;
   }
 }
diff --git a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
index 14cda3c..83eab94 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Entity/EntityFieldTest.php
@@ -8,9 +8,11 @@
 namespace Drupal\system\Tests\Entity;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldItemInterface;
 use Drupal\Core\Language\Language;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\TypedData\Type\StringInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 
@@ -534,13 +536,9 @@ public function testEntityConstraintValidation() {
     $entity = $this->createTestEntity('entity_test');
     $entity->save();
     // Create a reference field item and let it reference the entity.
-    $definition = array(
-      'type' => 'field_item:entity_reference',
-      'settings' => array(
-        'target_type' => 'entity_test',
-      ),
-      'label' => 'Test entity',
-    );
+    $definition = FieldDefinition::create('entity_reference')
+      ->setLabel('Test entity')
+      ->setFieldSetting('target_type', 'entity_test');
     $reference_field_item = \Drupal::TypedData()->create($definition);
     $reference = $reference_field_item->get('entity');
     $reference->setValue($entity);
@@ -561,13 +559,12 @@ public function testEntityConstraintValidation() {
     $this->assertEqual($violations->count(), 1);
 
     // Test bundle validation.
-    $definition = array(
-      'type' => 'field_item:entity_reference',
-      'settings' => array(
+    $definition = FieldDefinition::create('entity_reference')
+      ->setLabel('Test entity')
+      ->setFieldSettings(array(
         'target_type' => 'node',
         'target_bundle' => 'article',
-      ),
-    );
+      ));
     $reference_field_item = \Drupal::TypedData()->create($definition);
     $reference = $reference_field_item->get('entity');
     $reference->setValue($node);
diff --git a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
index 4de69dd..1408b47 100644
--- a/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/TypedData/TypedDataTest.php
@@ -7,6 +7,8 @@
 
 namespace Drupal\system\Tests\TypedData;
 
+use Drupal\Core\Field\FieldDefinition;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\Core\TypedData\ListDefinition;
 use Drupal\simpletest\DrupalUnitTestBase;
 use Drupal\Core\Datetime\DrupalDateTime;
@@ -51,6 +53,9 @@ public function setUp() {
    * @see \Drupal\Core\TypedData\TypedDataManager::create().
    */
   protected function createTypedData($definition, $value = NULL, $name = NULL) {
+    if (is_array($definition)) {
+      $definition = DataDefinition::create($definition['type']);
+    }
     $data = $this->typedData->create($definition, $value, $name);
     $this->assertTrue($data instanceof \Drupal\Core\TypedData\TypedDataInterface, 'Typed data object is an instance of the typed data interface.');
     return $data;
@@ -420,7 +425,7 @@ public function testTypedDataMaps() {
     // Test retrieving metadata.
     $this->assertEqual(array_keys($typed_data->getPropertyDefinitions()), array_keys($value));
     $definition = $typed_data->getPropertyDefinition('one');
-    $this->assertEqual($definition['type'], 'any');
+    $this->assertEqual($definition->getDataType(), 'any');
     $this->assertFalse($typed_data->getPropertyDefinition('invalid'));
 
     // Test getting and setting properties.
@@ -491,19 +496,17 @@ public function testTypedDataMaps() {
     $typed_data->set('zero', 'null');
     $this->assertEqual($typed_data->get('zero')->getValue(), 'null');
     $definition = $typed_data->getPropertyDefinition('zero');
-    $this->assertEqual($definition['type'], 'any', 'Definition for a new map entry returned.');
+    $this->assertEqual($definition->getDataType(), 'any', 'Definition for a new map entry returned.');
   }
 
   /**
    * Tests typed data validation.
    */
   public function testTypedDataValidation() {
-    $definition = array(
-      'type' => 'integer',
-      'constraints' => array(
+    $definition = DataDefinition::create('integer')
+      ->setConstraints(array(
         'Range' => array('min' => 5),
-      ),
-    );
+      ));
     $violations = $this->typedData->create($definition, 10)->validate();
     $this->assertEqual($violations->count(), 0);
 
@@ -518,25 +521,21 @@ public function testTypedDataValidation() {
     $this->assertIdentical($violations[0]->getRoot(), $integer, 'Root object returned.');
 
     // Test translating violation messages when pluralization is used.
-    $definition = array(
-      'type' => 'string',
-      'constraints' => array(
+    $definition = DataDefinition::create('string')
+      ->setConstraints(array(
         'Length' => array('min' => 10),
-      ),
-    );
+      ));
     $violations = $this->typedData->create($definition, "short")->validate();
     $this->assertEqual($violations->count(), 1);
     $message = t('This value is too short. It should have %limit characters or more.', array('%limit' => 10));
     $this->assertEqual($violations[0]->getMessage(), $message, 'Translated violation message retrieved.');
 
     // Test having multiple violations.
-    $definition = array(
-      'type' => 'integer',
-      'constraints' => array(
+    $definition = DataDefinition::create('integer')
+      ->setConstraints(array(
         'Range' => array('min' => 5),
         'Null' => array(),
-      ),
-    );
+      ));
     $violations = $this->typedData->create($definition, 10)->validate();
     $this->assertEqual($violations->count(), 1);
     $violations = $this->typedData->create($definition, 1)->validate();
@@ -544,12 +543,8 @@ public function testTypedDataValidation() {
 
     // Test validating property containers and make sure the NotNull and Null
     // constraints work with typed data containers.
-    $definition = array(
-      'type' => 'field_item:integer',
-      'constraints' => array(
-        'NotNull' => array(),
-      ),
-    );
+    $definition = FieldDefinition::create('integer')
+      ->setConstraints(array('NotNull' => array()));
     $field_item = $this->typedData->create($definition, array('value' => 10));
     $violations = $field_item->validate();
     $this->assertEqual($violations->count(), 0);
@@ -565,12 +560,8 @@ public function testTypedDataValidation() {
     $this->assertEqual($violations->count(), 1);
 
     // Test the Null constraint with typed data containers.
-    $definition = array(
-      'type' => 'field_item:float',
-      'constraints' => array(
-        'Null' => array(),
-      ),
-    );
+    $definition = FieldDefinition::create('float')
+      ->setConstraints(array('Null' => array()));
     $field_item = $this->typedData->create($definition, array('value' => 11.5));
     $violations = $field_item->validate();
     $this->assertEqual($violations->count(), 1);
@@ -590,10 +581,8 @@ public function testTypedDataValidation() {
     $this->assertTrue(isset($definitions['NotNull']), 'Constraint plugin found for type string.');
 
     // Test automatic 'required' validation.
-    $definition = array(
-      'type' => 'integer',
-      'required' => TRUE,
-    );
+    $definition = DataDefinition::create('integer')
+      ->setRequired(TRUE);
     $violations = $this->typedData->create($definition)->validate();
     $this->assertEqual($violations->count(), 1);
     $violations = $this->typedData->create($definition, 0)->validate();
@@ -601,10 +590,7 @@ public function testTypedDataValidation() {
 
     // Test validating a list of a values and make sure property paths starting
     // with "0" are created.
-    $definition = array(
-      'type' => 'field_item:integer',
-      'list' => TRUE,
-    );
+    $definition = FieldDefinition::create('integer');
     $violations = $this->typedData->create($definition, array(array('value' => 10)))->validate();
     $this->assertEqual($violations->count(), 0);
     $violations = $this->typedData->create($definition, array(array('value' => 'string')))->validate();
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
index b4ad49b..1d82a01 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\Core\Language\Language;
 
 /**
@@ -114,45 +115,39 @@ public function label($langcode = NULL) {
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $fields['id'] = array(
-      'label' => t('ID'),
-      'description' => t('The ID of the test entity.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $fields['uuid'] = array(
-      'label' => t('UUID'),
-      'description' => t('The UUID of the test entity.'),
-      'type' => 'uuid_field',
-    );
-    $fields['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The language code of the test entity.'),
-      'type' => 'language_field',
-    );
-    $fields['name'] = array(
-      'label' => t('Name'),
-      'description' => t('The name of the test entity.'),
-      'type' => 'string_field',
-      'translatable' => TRUE,
-      'property_constraints' => array(
-        'value' => array('Length' => array('max' => 32)),
-      ),
-    );
-    $fields['type'] = array(
-      'label' => t('Type'),
-      'description' => t('The bundle of the test entity.'),
-      'type' => 'string_field',
-      'required' => TRUE,
-      // @todo: Add allowed values validation.
-    );
-    $fields['user_id'] = array(
-      'label' => t('User ID'),
-      'description' => t('The ID of the associated user.'),
-      'type' => 'entity_reference_field',
-      'settings' => array('target_type' => 'user'),
-      'translatable' => TRUE,
-    );
+    $fields['uid'] = FieldDefinition::create('integer')
+      ->setLabel(t('ID'))
+      ->setDescription(t('The ID of the test entity.'))
+      ->setReadOnly(TRUE);
+
+    $fields['uuid'] = FieldDefinition::create('uuid')
+      ->setLabel(t('UUID'))
+      ->setDescription(t('The UUID of the test entity.'))
+      ->setReadOnly(TRUE);
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The language code of the test entity.'));
+
+    $fields['name'] = FieldDefinition::create('string')
+      ->setLabel(t('Name'))
+      ->setDescription(t('The name of the test entity.'))
+      ->setTranslatable(TRUE)
+      ->setPropertyConstraints('value', array('Length' => array('max' => 32)));
+
+    // @todo: Add allowed values validation.
+    $fields['type'] = FieldDefinition::create('string')
+      ->setLabel(t('Type'))
+      ->setDescription(t('The bundle of the test entity.'))
+      ->setRequired(TRUE);
+
+    $fields['user_id'] = FieldDefinition::create('entity_reference')
+      ->setLabel(t('User ID'))
+      ->setDescription(t('The ID of the associated user.'))
+      ->setFieldSettings(array('target_type' => 'user'))
+      ->setTranslatable(TRUE);
+
     return $fields;
   }
+
 }
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
index e73ff5e..817d6a9 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\entity_test\Entity;
 
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\entity_test\Entity\EntityTest;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
@@ -50,11 +51,11 @@ class EntityTestMul extends EntityTest {
    */
   public static function baseFieldDefinitions($entity_type) {
     $fields = parent::baseFieldDefinitions($entity_type);
-    $fields['default_langcode'] = array(
-      'label' => t('Default language'),
-      'description' => t('Flag to indicate whether this is the default language.'),
-      'type' => 'boolean_field',
-    );
+
+    $fields['default_langcode'] = FieldDefinition::create('boolean')
+      ->setLabel(t('Default language'))
+      ->setDescription(t('Flag to indicate whether this is the default language.'));
+
     return $fields;
   }
 
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
index 5b495f5..66503ea 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\entity_test\Entity;
 
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\entity_test\Entity\EntityTestRev;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
@@ -50,17 +51,16 @@ class EntityTestMulRev extends EntityTestRev {
    */
   public static function baseFieldDefinitions($entity_type) {
     $fields = parent::baseFieldDefinitions($entity_type);
-    $fields['revision_id'] = array(
-      'label' => t('ID'),
-      'description' => t('The version id of the test entity.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $fields['default_langcode'] = array(
-      'label' => t('Default language'),
-      'description' => t('Flag to inditcate whether this is the default language.'),
-      'type' => 'boolean_field',
-    );
+
+    $fields['revision_id'] = FieldDefinition::create('integer')
+      ->setLabel(t('Revision ID'))
+      ->setDescription(t('The version id of the test entity.'))
+      ->setReadOnly(TRUE);
+
+    $fields['default_langcode'] = FieldDefinition::create('boolean')
+      ->setLabel(t('Default language'))
+      ->setDescription(t('Flag to indicate whether this is the default language.'));
+
     return $fields;
   }
 
diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php
index 4935645..19d3551 100644
--- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php
+++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\entity_test\Entity;
 
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\entity_test\Entity\EntityTest;
 use Drupal\Core\Entity\Annotation\EntityType;
 use Drupal\Core\Annotation\Translation;
@@ -69,12 +70,13 @@ public function getRevisionId() {
    */
   public static function baseFieldDefinitions($entity_type) {
     $fields = parent::baseFieldDefinitions($entity_type);
-    $fields['revision_id'] = array(
-      'label' => t('ID'),
-      'description' => t('The version id of the test entity.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
+
+    $fields['revision_id'] = FieldDefinition::create('integer')
+      ->setLabel(t('Revision ID'))
+      ->setDescription(t('The version id of the test entity.'))
+      ->setReadOnly(TRUE);
+
     return $fields;
   }
+
 }
diff --git a/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php b/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php
index 032da92..9efc5d4 100644
--- a/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php
+++ b/core/modules/telephone/lib/Drupal/telephone/Plugin/Field/FieldType/TelephoneItem.php
@@ -8,6 +8,7 @@
 namespace Drupal\telephone\Plugin\Field\FieldType;
 
 use Drupal\Core\Field\ConfigFieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 
 /**
@@ -50,10 +51,8 @@ public static function schema(FieldInterface $field) {
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'string',
-        'label' => t('Telephone number'),
-      );
+      static::$propertyDefinitions['value'] = DataDefinition::create('string')
+        ->setLabel(t('Telephone number'));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php
index 07e3950..897a146 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextItemBase.php
@@ -9,6 +9,7 @@
 
 use Drupal\Core\Field\ConfigFieldItemBase;
 use Drupal\Core\Field\PrepareCacheInterface;
+use Drupal\Core\TypedData\DataDefinition;
 
 /**
  * Base class for 'text' configurable field types.
@@ -27,24 +28,20 @@
    */
   public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
-      static::$propertyDefinitions['value'] = array(
-        'type' => 'string',
-        'label' => t('Text value'),
-      );
-      static::$propertyDefinitions['format'] = array(
-        'type' => 'filter_format',
-        'label' => t('Text format'),
-      );
-      static::$propertyDefinitions['processed'] = array(
-        'type' => 'string',
-        'label' => t('Processed text'),
-        'description' => t('The text value with the text format applied.'),
-        'computed' => TRUE,
-        'class' => '\Drupal\text\TextProcessed',
-        'settings' => array(
+      static::$propertyDefinitions['value'] = DataDefinition::create('string')
+        ->setLabel(t('Text value'));
+
+      static::$propertyDefinitions['format'] = DataDefinition::create('filter_format')
+        ->setLabel(t('Text format'));
+
+      static::$propertyDefinitions['processed'] = DataDefinition::create('string')
+        ->setLabel(t('Processed text'))
+        ->setDescription(t('The text value with the text format applied.'))
+        ->setComputed(TRUE)
+        ->setClass('\Drupal\text\TextProcessed')
+        ->setSettings(array(
           'text source' => 'value',
-        ),
-      );
+        ));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php
index 0d3c138..08525d1 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/Field/FieldType/TextWithSummaryItem.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\text\Plugin\Field\FieldType;
 
+use Drupal\Core\TypedData\DataDefinition;
 use Drupal\field\FieldInterface;
 
 /**
@@ -40,20 +41,17 @@ public function getPropertyDefinitions() {
     if (!isset(static::$propertyDefinitions)) {
       static::$propertyDefinitions = parent::getPropertyDefinitions();
 
-      static::$propertyDefinitions['summary'] = array(
-        'type' => 'string',
-        'label' => t('Summary text value'),
-      );
-      static::$propertyDefinitions['summary_processed'] = array(
-        'type' => 'string',
-        'label' => t('Processed summary text'),
-        'description' => t('The summary text value with the text format applied.'),
-        'computed' => TRUE,
-        'class' => '\Drupal\text\TextProcessed',
-        'settings' => array(
+      static::$propertyDefinitions['summary'] = DataDefinition::create('string')
+        ->setLabel(t('Summary text value'));
+
+      static::$propertyDefinitions['summary_processed'] = DataDefinition::create('string')
+        ->setLabel(t('Processed summary text'))
+        ->setDescription(t('The summary text value with the text format applied.'))
+        ->setComputed(TRUE)
+        ->setClass('\Drupal\text\TextProcessed')
+        ->setSettings(array(
           'text source' => 'summary',
-        ),
-      );
+        ));
     }
     return static::$propertyDefinitions;
   }
diff --git a/core/modules/text/lib/Drupal/text/TextProcessed.php b/core/modules/text/lib/Drupal/text/TextProcessed.php
index dd1fe8e..0f69102 100644
--- a/core/modules/text/lib/Drupal/text/TextProcessed.php
+++ b/core/modules/text/lib/Drupal/text/TextProcessed.php
@@ -7,9 +7,9 @@
 
 namespace Drupal\text;
 
+use Drupal\Core\TypedData\DataDefinitionInterface;
 use Drupal\Core\TypedData\TypedDataInterface;
 use Drupal\Core\TypedData\TypedData;
-use Drupal\Core\TypedData\ReadOnlyException;
 
 /**
  * A computed property for processing text with a format.
@@ -29,7 +29,7 @@ class TextProcessed extends TypedData {
   /**
    * Overrides TypedData::__construct().
    */
-  public function __construct($definition, $name = NULL, TypedDataInterface $parent = NULL) {
+  public function __construct(DataDefinitionInterface $definition, $name = NULL, TypedDataInterface $parent = NULL) {
     parent::__construct($definition, $name, $parent);
 
     if (!isset($definition['settings']['text source'])) {
diff --git a/core/modules/user/lib/Drupal/user/Entity/User.php b/core/modules/user/lib/Drupal/user/Entity/User.php
index 3d1815d..530fe83 100644
--- a/core/modules/user/lib/Drupal/user/Entity/User.php
+++ b/core/modules/user/lib/Drupal/user/Entity/User.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\ContentEntityBase;
 use Drupal\Core\Entity\EntityStorageControllerInterface;
 use Drupal\Core\Entity\EntityMalformedException;
+use Drupal\Core\Field\FieldDefinition;
 use Drupal\user\UserInterface;
 
 /**
@@ -429,129 +430,100 @@ public function setUsername($username) {
    * {@inheritdoc}
    */
   public static function baseFieldDefinitions($entity_type) {
-    $properties['uid'] = array(
-      'label' => t('User ID'),
-      'description' => t('The user ID.'),
-      'type' => 'integer_field',
-      'read-only' => TRUE,
-    );
-    $properties['uuid'] = array(
-      'label' => t('UUID'),
-      'description' => t('The user UUID.'),
-      'type' => 'uuid_field',
-      'read-only' => TRUE,
-    );
-    $properties['langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t('The user language code.'),
-      'type' => 'language_field',
-    );
-    $properties['preferred_langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t("The user's preferred langcode for receiving emails and viewing the site."),
-      'type' => 'language_field',
-    );
-    $properties['preferred_admin_langcode'] = array(
-      'label' => t('Language code'),
-      'description' => t("The user's preferred langcode for viewing administration pages."),
-      'type' => 'language_field',
-    );
-    $properties['name'] = array(
-      'label' => t('Name'),
-      'description' => t('The name of this user'),
-      'type' => 'string_field',
-      'settings' => array('default_value' => ''),
-      'property_constraints' => array(
-        // No Length contraint here because the UserName constraint also covers
+    $fields['uid'] = FieldDefinition::create('integer')
+      ->setLabel(t('User ID'))
+      ->setDescription(t('The user ID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['uuid'] = FieldDefinition::create('uuid')
+      ->setLabel(t('UUID'))
+      ->setDescription(t('The user UUID.'))
+      ->setReadOnly(TRUE);
+
+    $fields['langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Language code'))
+      ->setDescription(t('The user language code.'));
+
+    $fields['preferred_langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Preferred admin language code'))
+      ->setDescription(t("The user's preferred language code for receiving emails and viewing the site."));
+
+    $fields['preferred_admin_langcode'] = FieldDefinition::create('language')
+      ->setLabel(t('Preferred language code'))
+      ->setDescription(t("The user's preferred language code for viewing administration pages."));
+
+    $fields['name'] = FieldDefinition::create('string')
+      ->setLabel(t('Name'))
+      ->setDescription(t('The name of this user.'))
+      ->setFieldSetting('default_value', '')
+      ->setPropertyConstraints('value', array(
+        // No Length constraint here because the UserName constraint also covers
         // that.
-        'value' => array(
-          'UserName' => array(),
-          'UserNameUnique' => array(),
-        ),
-      ),
-    );
-    $properties['pass'] = array(
-      'label' => t('Password'),
-      'description' => t('The password of this user (hashed)'),
-      'type' => 'string_field',
-    );
-    $properties['mail'] = array(
-      'label' => t('E-mail'),
-      'description' => t('The e-mail of this user'),
-      'type' => 'email_field',
-      'settings' => array('default_value' => ''),
-      'property_constraints' => array(
-        'value' => array('UserMailUnique' => array()),
-      ),
-    );
-    $properties['signature'] = array(
-      'label' => t('Signature'),
-      'description' => t('The signature of this user'),
-      'type' => 'string_field',
-      'property_constraints' => array(
-        'value' => array('Length' => array('max' => 255)),
-      ),
-    );
-    $properties['signature_format'] = array(
-      'label' => t('Signature format'),
-      'description' => t('The signature format of this user'),
-      // @todo Convert the type to filter_format once
-      // https://drupal.org/node/1758622 is comitted
-      'type' => 'string_field',
-    );
-    $properties['theme'] = array(
-      'label' => t('Theme'),
-      'description' => t('The default theme of this user'),
-      'type' => 'string_field',
-      'property_constraints' => array(
-        'value' => array('Length' => array('max' => DRUPAL_EXTENSION_NAME_MAX_LENGTH)),
-      ),
-    );
-    $properties['timezone'] = array(
-      'label' => t('Timezone'),
-      'description' => t('The timezone of this user'),
-      'type' => 'string_field',
-      'property_constraints' => array(
-        'value' => array('Length' => array('max' => 32)),
-      ),
-    );
-    $properties['status'] = array(
-      'label' => t('User status'),
-      'description' => t('Whether the user is active (1) or blocked (0).'),
-      'type' => 'boolean_field',
-      'settings' => array('default_value' => 1),
-    );
-    $properties['created'] = array(
-      'label' => t('Created'),
-      'description' => t('The time that the node was created.'),
-      'type' => 'integer_field',
-    );
-    $properties['access'] = array(
-      'label' => t('Last access'),
-      'description' => t('The time that the user last accessed the site.'),
-      'type' => 'integer_field',
-      'settings' => array('default_value' => 0),
-    );
-    $properties['login'] = array(
-      'label' => t('Last login'),
-      'description' => t('The time that the user last logged in.'),
-      'type' => 'integer_field',
-      'settings' => array('default_value' => 0),
-    );
-    $properties['init'] = array(
-      'label' => t('Init'),
-      'description' => t('The email address used for initial account creation.'),
-      'type' => 'email_field',
-      'settings' => array('default_value' => ''),
-    );
-    $properties['roles'] = array(
-      'label' => t('Roles'),
-      'description' => t('The roles the user has.'),
-      // @todo Convert this to entity_reference_field, see
-      // https://drupal.org/node/2044859
-      'type' => 'string_field',
-    );
-    return $properties;
+        'UserName' => array(),
+        'UserNameUnique' => array(),
+      ));
+
+    $fields['pass'] = FieldDefinition::create('string')
+      ->setLabel(t('Password'))
+      ->setDescription(t('The password of this user (hashed).'));
+
+    $fields['mail'] = FieldDefinition::create('email')
+      ->setLabel(t('Email'))
+      ->setDescription(t('The email of this user.'))
+      ->setFieldSetting('default_value', '')
+      ->setPropertyConstraints('value', array('UserMailUnique' => array()));
+
+    // @todo Convert to a text field in https://drupal.org/node/1548204.
+    $fields['signature'] = FieldDefinition::create('string')
+      ->setLabel(t('Signature'))
+      ->setDescription(t('The signature of this user.'))
+      ->setPropertyConstraints('value', array('Length' => array('max' => 255)));
+    $fields['signature_format'] = FieldDefinition::create('string')
+      ->setLabel(t('Signature format'))
+      ->setDescription(t('The signature format of this user.'));
+
+    $fields['theme'] = FieldDefinition::create('string')
+      ->setLabel(t('Theme'))
+      ->setDescription(t('The default theme of this user.'))
+      ->setPropertyConstraints('value', array('Length' => array('max' => DRUPAL_EXTENSION_NAME_MAX_LENGTH)));
+
+    $fields['timezone'] = FieldDefinition::create('string')
+      ->setLabel(t('Timezone'))
+      ->setDescription(t('The timezone of this user.'))
+      ->setPropertyConstraints('value', array('Length' => array('max' => 32)));
+
+    $fields['status'] = FieldDefinition::create('boolean')
+      ->setLabel(t('User status'))
+      ->setDescription(t('Whether the user is active (1) or blocked (0).'))
+      ->setFieldSetting('default_value', 1);
+
+    // @todo Candidate for timestamp.
+    $fields['created'] = FieldDefinition::create('integer')
+      ->setLabel(t('Created'))
+      ->setDescription(t('The time that the user was created.'));
+
+    // @todo Candidate for timestamp.
+    $fields['access'] = FieldDefinition::create('integer')
+      ->setLabel(t('Last access'))
+      ->setDescription(t('The time that the user last accessed the site.'))
+      ->setFieldSetting('default_value', 0);
+
+    // @todo Candidate for timestamp.
+    $fields['login'] = FieldDefinition::create('integer')
+      ->setLabel(t('Last login'))
+      ->setDescription(t('The time that the user last logged in.'))
+      ->setFieldSetting('default_value', 0);
+
+    $fields['init'] = FieldDefinition::create('email')
+      ->setLabel(t('Initial email'))
+      ->setDescription(t('The email address used for initial account creation.'))
+      ->setFieldSetting('default_value', '');
+
+    $fields['roles'] = FieldDefinition::create('string')
+      ->setLabel(t('Roles'))
+      ->setDescription(t('The roles the user has.'));
+
+    return $fields;
   }
 
 }
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 5751f02..0dc5077 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -9,6 +9,7 @@
 use Drupal\user\UserInterface;
 use Drupal\user\RoleInterface;
 use Drupal\Core\Template\Attribute;
+use Drupal\Core\TypedData\DataDefinition;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
 use Drupal\menu_link\Entity\MenuLink;
@@ -350,10 +351,9 @@ function user_load_by_name($name) {
  *
  */
 function user_validate_name($name) {
-  $data = \Drupal::typedData()->create(array(
-    'type' => 'string',
-    'constraints' => array('UserName' => array()),
-  ));
+  $definition = DataDefinition::create('string')
+    ->setConstraints(array('UserName' => array()));
+  $data = \Drupal::typedData()->create($definition);
   $data->setValue($name);
   $violations = $data->validate();
   if (count($violations) > 0) {