diff --git a/core/lib/Drupal/Core/Field/FieldItemListComputed.php b/core/lib/Drupal/Core/Field/FieldItemListComputed.php
new file mode 100644
index 0000000000..30c076957a
--- /dev/null
+++ b/core/lib/Drupal/Core/Field/FieldItemListComputed.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace Drupal\Core\Field;
+
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Represents a computed entity field; that is, a list of field item objects.
+ */
+abstract class FieldItemListComputed extends FieldItemList {
+
+  /**
+   * Numerically indexed array of field items.
+   *
+   * @var \Drupal\Core\Field\FieldItemInterface[]
+   */
+  protected $list = array();
+
+  /**
+   * This will populate the field item list with computed values.
+   */
+  public function computeItems() {
+    $this->list = [];
+    $values = $this->computeItemValues();
+    if (is_array($values) && !empty($values)) {
+      foreach ($values as $delta => $value) {
+        $this->list[] = $this->createItem($delta, $value);
+      }
+    }
+  }
+
+  /**
+   * This should compute the values that are used to create the field items.
+   *
+   * @return array
+   *   The values for the field items.
+   */
+  protected abstract function computeItemValues();
+
+  /**
+   * This will do nothing as computed lists are readonly by default.
+   */
+  public function setValue($values, $notify = TRUE) {}
+
+  /**
+   * This will do nothing as computed lists are readonly by default.
+   */
+  public function appendItem($value = NULL) {}
+
+  /**
+   * This will do nothing as computed lists are readonly by default.
+   */
+  public function defaultValuesForm(array &$form, FormStateInterface $form_state) {}
+
+  /**
+   * This will do nothing as computed lists are readonly by default.
+   */
+  public function removeItem($index) {}
+
+  /**
+   * This will do nothing as computed lists are readonly by default.
+   */
+  public function set($index, $value) {}
+
+}
diff --git a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
index 4f756dadf2..4691ea858a 100644
--- a/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
+++ b/core/lib/Drupal/Core/TypedData/Plugin/DataType/ItemList.php
@@ -97,10 +97,7 @@ public function get($index) {
     if (!is_numeric($index)) {
       throw new \InvalidArgumentException('Unable to get a value with a non-numeric delta in a list.');
     }
-    // Automatically create the first item for computed fields.
-    if ($index == 0 && !isset($this->list[0]) && $this->definition->isComputed()) {
-      $this->list[0] = $this->createItem(0);
-    }
+
     return isset($this->list[$index]) ? $this->list[$index] : NULL;
   }
 
diff --git a/core/lib/Drupal/Core/TypedData/TypedDataManager.php b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
index dbf0d5fec5..17f3b0211e 100644
--- a/core/lib/Drupal/Core/TypedData/TypedDataManager.php
+++ b/core/lib/Drupal/Core/TypedData/TypedDataManager.php
@@ -7,6 +7,7 @@
 use Drupal\Core\DependencyInjection\ClassResolverInterface;
 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Drupal\Core\Field\FieldItemListComputed;
 use Drupal\Core\Plugin\DefaultPluginManager;
 use Drupal\Core\TypedData\Validation\ExecutionContextFactory;
 use Drupal\Core\TypedData\Validation\RecursiveValidator;
@@ -199,6 +200,9 @@ public function getPropertyInstance(TypedDataInterface $object, $property_name,
     $property->setContext($property_name, $object);
     if (isset($value)) {
       $property->setValue($value, FALSE);
+    } elseif ($property instanceof FieldItemListComputed) {
+      // populate the computed list with values as there are no initial values to set.
+      $property->computeItems();
     }
     return $property;
   }
diff --git a/core/modules/field/tests/modules/field_computed_test/field_computed_test.info.yml b/core/modules/field/tests/modules/field_computed_test/field_computed_test.info.yml
new file mode 100644
index 0000000000..42f6216f07
--- /dev/null
+++ b/core/modules/field/tests/modules/field_computed_test/field_computed_test.info.yml
@@ -0,0 +1,6 @@
+name: 'Field Computed Test'
+type: module
+description: 'Support module for the computed field tests.'
+core: 8.x
+package: Testing
+version: VERSION
diff --git a/core/modules/field/tests/modules/field_computed_test/field_computed_test.module b/core/modules/field/tests/modules/field_computed_test/field_computed_test.module
new file mode 100644
index 0000000000..28bd677665
--- /dev/null
+++ b/core/modules/field/tests/modules/field_computed_test/field_computed_test.module
@@ -0,0 +1,60 @@
+<?php
+
+use Drupal\Core\Entity\EntityTypeInterface;
+use Drupal\Core\Field\BaseFieldDefinition;
+
+function field_computed_test_entity_base_field_info(EntityTypeInterface $entity) {
+  if ($entity->id() === 'node') {
+    $fields = array();
+
+    $fields['field_dice_count'] = BaseFieldDefinition::create('integer')
+      ->setCustomStorage(false)
+      ->setLabel(t('Dice count'))
+      ->setDisplayOptions('view', array(
+        'label' => 'inline',
+        'type' => 'text_textfield',
+        'weight' => 0,
+      ))
+      ->setDisplayOptions('form', array(
+        'type' => 'integer',
+        'weight' => 10,
+      ))
+      ->setDisplayConfigurable('form', TRUE);
+
+    // set a custom list class an explicitly define the field to be computed
+    $fields['field_dice_result'] = BaseFieldDefinition::create('integer')
+      ->setLabel(t('Dice result'))
+      ->setClass('\Drupal\field_computed_test\Plugin\Field\FieldType\DiceItemList')
+      ->setComputed(TRUE)
+      ->setDisplayOptions('view', array(
+        'label' => 'inline',
+        'type' => 'number_integer',
+        'weight' => 0,
+      ));
+
+    // set a custom list class and rely on that class to mark the field as computed
+    $fields['field_dice_result_v2'] = BaseFieldDefinition::create('integer')
+      ->setLabel(t('Dice result V2'))
+      ->setClass('\Drupal\field_computed_test\Plugin\Field\FieldType\DiceItemList')
+      ->setDisplayOptions('view', array(
+        'label' => 'inline',
+        'type' => 'number_integer',
+        'weight' => 0,
+      ));
+
+    // use a field type which uses a list class that marks the field as computed
+    $fields['field_dice_result_v3'] = BaseFieldDefinition::create('dice')
+      ->setLabel(t('Dice result V3'))
+      ->setDisplayOptions('view', array(
+        'label' => 'inline',
+        'weight' => 0,
+      ))
+      ->setDisplayOptions('form', array(
+        'type' => 'integer',
+        'weight' => 10,
+      ));
+
+    return $fields;
+  }
+
+}
diff --git a/core/modules/field/tests/modules/field_computed_test/src/Plugin/Field/FieldType/DiceItem.php b/core/modules/field/tests/modules/field_computed_test/src/Plugin/Field/FieldType/DiceItem.php
new file mode 100644
index 0000000000..cb99035727
--- /dev/null
+++ b/core/modules/field/tests/modules/field_computed_test/src/Plugin/Field/FieldType/DiceItem.php
@@ -0,0 +1,39 @@
+<?php
+
+namespace Drupal\field_computed_test\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\TypedData\DataDefinition;
+
+/**
+ * @FieldType(
+ *   id = "dice",
+ *   label = @Translation("Dice field"),
+ *   description = @Translation("Dummy field type used for tests."),
+ *   default_widget = "number",
+ *   default_formatter = "number_integer",
+ *   list_class = "\Drupal\field_computed_test\Plugin\Field\FieldType\DiceItemList"
+ * )
+ */
+class DiceItem extends FieldItemBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
+    $properties['value'] = DataDefinition::create('integer')
+      ->setLabel(t('Integer value'));
+    return $properties;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
+    return [
+      'columns' => [],
+    ];
+  }
+
+}
diff --git a/core/modules/field/tests/modules/field_computed_test/src/Plugin/Field/FieldType/DiceItemList.php b/core/modules/field/tests/modules/field_computed_test/src/Plugin/Field/FieldType/DiceItemList.php
new file mode 100644
index 0000000000..03aca20992
--- /dev/null
+++ b/core/modules/field/tests/modules/field_computed_test/src/Plugin/Field/FieldType/DiceItemList.php
@@ -0,0 +1,26 @@
+<?php
+
+namespace Drupal\field_computed_test\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\FieldItemListComputed;
+
+/**
+ * Represents a configurable dice result.
+ */
+class DiceItemList extends FieldItemListComputed {
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function computeItemValues() {
+    $items_count = $this->getEntity()->field_dice_count->value;
+    $values = [];
+    foreach (range(0, $items_count - 1) as $delta) {
+      $values[$delta] = [
+        'value' => rand(1, 6),
+      ];
+    }
+    return $values;
+  }
+
+}
diff --git a/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php b/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php
index 2b929f3608..1f4bfa48fc 100644
--- a/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php
+++ b/core/modules/views/tests/src/Unit/Plugin/field/FieldTest.php
@@ -83,6 +83,13 @@ protected function setUp() {
       ->method('getDefaultFieldSettings')
       ->willReturn([]);
 
+    $typed_data_manager = $this->getMock('Drupal\Component\Plugin\PluginManagerInterface');
+    // @todo: maybe use a reasonable argument
+    $typed_data_manager->expects($this->any())
+      ->method('getDefinition')
+      ->with($this->anything())
+      ->will($this->returnValue(['list_class' => '\Drupal\Core\Field\FieldItemList']));
+
     $this->languageManager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface');
     $this->renderer = $this->getMock('Drupal\Core\Render\RendererInterface');
 
@@ -94,6 +101,7 @@ protected function setUp() {
 
     $this->container = new ContainerBuilder();
     $this->container->set('plugin.manager.field.field_type', $this->fieldTypePluginManager);
+    $this->container->set('typed_data_manager', $typed_data_manager);
     \Drupal::setContainer($this->container);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php b/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php
index 341ed9cf8c..a7918fb9b7 100644
--- a/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/BaseFieldDefinitionTest.php
@@ -64,8 +64,16 @@ protected function setUp() {
       ->with($this->fieldType)
       ->will($this->returnValue($this->fieldTypeDefinition['field_settings']));
 
+    $typed_data_manager = $this->getMock('Drupal\Component\Plugin\PluginManagerInterface');
+    // @todo: maybe use a reasonable argument
+    $typed_data_manager->expects($this->any())
+      ->method('getDefinition')
+      ->with($this->anything())
+      ->will($this->returnValue(['list_class' => '\Drupal\Core\Field\FieldItemList']));
+
     $container = new ContainerBuilder();
     $container->set('plugin.manager.field.field_type', $field_type_manager);
+    $container->set('typed_data_manager', $typed_data_manager);
     \Drupal::setContainer($container);
   }
 
diff --git a/core/tests/Drupal/Tests/Core/Entity/TypedData/EntityAdapterUnitTest.php b/core/tests/Drupal/Tests/Core/Entity/TypedData/EntityAdapterUnitTest.php
index 953daac887..d5832d7fbd 100644
--- a/core/tests/Drupal/Tests/Core/Entity/TypedData/EntityAdapterUnitTest.php
+++ b/core/tests/Drupal/Tests/Core/Entity/TypedData/EntityAdapterUnitTest.php
@@ -141,8 +141,15 @@ protected function setUp() {
     $this->typedDataManager = $this->getMock(TypedDataManagerInterface::class);
     $this->typedDataManager->expects($this->any())
       ->method('getDefinition')
-      ->with('entity')
-      ->will($this->returnValue(['class' => '\Drupal\Core\Entity\Plugin\DataType\EntityAdapter']));
+      ->will($this->returnCallback(function($plugin_id){
+        switch ($plugin_id) {
+          case 'entity':
+            return ['class' => '\Drupal\Core\Entity\Plugin\DataType\EntityAdapter'];
+          default:
+            // @todo: maybe use a reasonable argument value
+            return ['list_class' => '\Drupal\Core\Field\FieldItemList'];
+        }
+      }));
     $this->typedDataManager->expects($this->any())
       ->method('getDefaultConstraints')
       ->willReturn([]);
