diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index e7883bb..459c973 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -42,12 +42,14 @@ uri:
 mapping:
   label: Mapping
   class: '\Drupal\Core\Config\Schema\Mapping'
+  definition_class: '\Drupal\Core\TypedData\MapDataDefinition'
 sequence:
   label: Sequence
   class: '\Drupal\Core\Config\Schema\Sequence'
-
+  definition_class: '\Drupal\Core\TypedData\ListDataDefinition'
+  
 # Simple extended data types:
-
+ 
 # Human readable string that must be plain text and editable with a text field.
 label:
   type: string
diff --git a/core/lib/Drupal/Core/Config/Schema/Element.php b/core/lib/Drupal/Core/Config/Schema/Element.php
index 2563ec5..c492d42 100644
--- a/core/lib/Drupal/Core/Config/Schema/Element.php
+++ b/core/lib/Drupal/Core/Config/Schema/Element.php
@@ -28,4 +28,13 @@ protected function parseElement($key, $data, $definition) {
     return \Drupal::service('config.typed')->create($definition, $data, $key, $this);
   }
 
+  /**
+   * Build data definition object for contained elements.
+   *
+   * @return \Drupal\Core\TypedData\DataDefinitionInterface
+   */
+  protected function buildDataDefinition($definition, $value, $key) {
+    return  \Drupal::service('config.typed')->buildDataDefinition($definition, $value, $key, $this);
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Config/Schema/Mapping.php b/core/lib/Drupal/Core/Config/Schema/Mapping.php
index 19fb596..5729390 100644
--- a/core/lib/Drupal/Core/Config/Schema/Mapping.php
+++ b/core/lib/Drupal/Core/Config/Schema/Mapping.php
@@ -20,11 +20,20 @@
 class Mapping extends ArrayElement implements ComplexDataInterface {
 
   /**
+   * An array of data definitions.
+   *
+   * @var \Drupal\Core\TypedData\DataDefinitionInterface[]
+   */
+  protected $propertyDefinitions;
+
+  /**
    * Overrides ArrayElement::parse()
+   *
+   * Note this only returns elements that have a data definition.
    */
   protected function parse() {
     $elements = array();
-    foreach ($this->definition['mapping'] as $key => $definition) {
+    foreach ($this->getPropertyDefinitions() as $key => $definition) {
       if (isset($this->value[$key]) || array_key_exists($key, $this->value)) {
         $elements[$key] = $this->parseElement($key, $this->value[$key], $definition);
       }
@@ -103,13 +112,12 @@ public function toArray() {
    * @param string $name
    *   The name of property.
    *
-   * @return array|null
+   * @return \Drupal\Core\TypedData\DataDefinitionInterface|null
    *   The definition of the property or NULL if the property does not exist.
    */
   public function getPropertyDefinition($name) {
-    if (isset($this->definition['mapping'][$name])) {
-      return $this->definition['mapping'][$name];
-    }
+    $definitions = $this->getPropertyDefinitions();
+    return isset($definitions[$name]) ? isset($definitions[$name]) : NULL;
   }
 
   /**
@@ -120,11 +128,14 @@ public function getPropertyDefinition($name) {
    *   property name.
    */
   public function getPropertyDefinitions() {
-    $list = array();
-    foreach ($this->getAllKeys() as $key) {
-      $list[$key] = $this->getPropertyDefinition($key);
+    if (!isset($this->propertyDefinitions)) {
+      $this->propertyDefinitions = array();
+      foreach ($this->definition['mapping'] as $key => $definition) {
+        $value = isset($this->value[$key]) ? $this->value[$key] : NULL;
+        $this->propertyDefinitions[$key] = $this->buildDataDefinition($definition, $value, $key);
+      }
     }
-    return $list;
+    return $this->propertyDefinitions;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/Schema/Sequence.php b/core/lib/Drupal/Core/Config/Schema/Sequence.php
index 720b850..79e27ba 100644
--- a/core/lib/Drupal/Core/Config/Schema/Sequence.php
+++ b/core/lib/Drupal/Core/Config/Schema/Sequence.php
@@ -15,13 +15,22 @@
 class Sequence extends ArrayElement implements ListInterface {
 
   /**
+   * Data definition
+   *
+   * @var \Drupal\Core\TypedData\DataDefinitionInterface
+   */
+  protected $itemDefinition;
+
+  /**
    * Overrides ArrayElement::parse()
    */
   protected function parse() {
-    $definition = $this->getItemDefinition();
+    // Get the generic definition and reprocess it for all items.
+    $definition = isset($this->definition['sequence'][0]) ? $this->definition['sequence'][0] : array();
     $elements = array();
     foreach ($this->value as $key => $value) {
-      $elements[$key] = $this->parseElement($key, $value, $definition);
+      $data_definition =  $this->buildDataDefinition($definition, $value, $key);
+      $elements[$key] = $this->parseElement($key, $value, $data_definition);
     }
     return $elements;
   }
@@ -37,7 +46,11 @@ public function isEmpty() {
    * Implements Drupal\Core\TypedData\ListInterface::getItemDefinition().
    */
   public function getItemDefinition() {
-    return $this->definition['sequence'][0];
+    if (!isset($this->itemDefinition)) {
+      $definition = isset($this->definition['sequence'][0]) ? $this->definition['sequence'][0] : array();
+      $this->itemDefinition = $this->buildDataDefinition($definition);
+    }
+    return $this->itemDefinition;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/StorableConfigBase.php b/core/lib/Drupal/Core/Config/StorableConfigBase.php
index 4a5fd1d..8151e4f 100644
--- a/core/lib/Drupal/Core/Config/StorableConfigBase.php
+++ b/core/lib/Drupal/Core/Config/StorableConfigBase.php
@@ -128,7 +128,8 @@ public function getStorage() {
   protected function getSchemaWrapper() {
     if (!isset($this->schemaWrapper)) {
       $definition = $this->typedConfigManager->getDefinition($this->name);
-      $this->schemaWrapper = $this->typedConfigManager->create($definition, $this->data);
+      $data_definition = $this->typedConfigManager->buildDataDefinition($definition, $this->data);
+      $this->schemaWrapper = $this->typedConfigManager->create($data_definition, $this->data);
     }
     return $this->schemaWrapper;
   }
diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php
index 2032f4c..66b7332 100644
--- a/core/lib/Drupal/Core/Config/TypedConfigManager.php
+++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php
@@ -12,11 +12,17 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Cache\CacheBackendInterface;
+use Drupal\Core\TypedData\DataDefinitionInterface;
+use Drupal\Core\TypedData\DataDefinition;
+use Drupal\Core\TypedData\ListDataDefinition;
+use Drupal\Core\TypedData\ListDataDefinitionInterface;
+use Drupal\Core\TypedData\MapDataDefinition;
+use Drupal\Core\TypedData\TypedDataManager;
 
 /**
  * Manages config type plugins.
  */
-class TypedConfigManager extends PluginManagerBase implements TypedConfigManagerInterface {
+class TypedConfigManager extends TypedDataManager implements TypedConfigManagerInterface {
 
   /**
    * The cache ID for the definitions.
@@ -80,19 +86,34 @@ public function __construct(StorageInterface $configStorage, StorageInterface $s
    */
   public function get($name) {
     $data = $this->configStorage->read($name);
-    $definition = $this->getDefinition($name);
-    return $this->create($definition, $data);
+    $type_definition = $this->getDefinition($name);
+    $data_definition =  $this->buildDataDefinition($type_definition, $data);
+    return $this->create($data_definition, $data);
   }
 
   /**
-   * {@inheritdoc}
+   * Creates a new data definition object from a type definition array and
+   * actual configuration data.
+   *
+   * @param array $definition
+   *   The base type definition array, for which a data definition should be created.
+   * @param $value
+   *   Optional value of the configuraiton element.
+   * @param string $name
+   *   Optional name of the configuration element.
+   * @param object $parent
+   *   Optional parent element
+   *
+   * @return \Drupal\Core\TypedData\DataDefinitionInterface
+   *   A data definition for the given data type.
+   *
+   * @see \Drupal\Core\TypedData\TypedDataManager::createListDataDefinition()
    */
-  public function create(array $definition, $value = NULL, $name = NULL, $parent = NULL) {
-    if (!isset($definition['type'])) {
-      // By default elements without a type are undefined.
-      $definition['type'] = 'undefined';
-    }
-    elseif (strpos($definition['type'], ']')) {
+  public function buildDataDefinition(array $definition, $value = NULL, $name = NULL, $parent = NULL) {
+    // Add default values for data type and replace variables.
+    $definition += array('type' => 'undefined');
+
+    if (strpos($definition['type'], ']')) {
       // Replace variable names in definition.
       $replace = is_array($value) ? $value : array();
       if (isset($parent)) {
@@ -103,45 +124,18 @@ public function create(array $definition, $value = NULL, $name = NULL, $parent =
       }
       $definition['type'] = $this->replaceName($definition['type'], $replace);
     }
-    // Create typed config object.
-    $wrapper = $this->createInstance($definition['type'], array(
-      'data_definition' => $definition,
-      'name' => $name,
-      'parent' => $parent,
-    ));
-    if (isset($value)) {
-      $wrapper->setValue($value, FALSE);
-    }
-    return $wrapper;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function createInstance($data_type, array $configuration = array()) {
-    $data_definition = $configuration['data_definition'];
-    $type_definition = $this->getDefinition($data_type);
-
-    if (!isset($type_definition)) {
-      throw new \InvalidArgumentException(String::format('Invalid data type %plugin_id has been given.', array('%plugin_id' => $data_type)));
-    }
+    // Add default values from type definition.
+    $definition += $this->getDefinition($definition['type']);
 
-    // Allow per-data definition overrides of the used classes, i.e. take over
-    // classes specified in the type definition.
-    $data_definition += $type_definition;
+    $data_definition = $this->createDataDefinition($definition['type']);
 
-    $key = empty($data_definition['list']) ? 'class' : 'list class';
-    if (isset($data_definition[$key])) {
-      $class = $data_definition[$key];
-    }
-    elseif (isset($type_definition[$key])) {
-      $class = $type_definition[$key];
-    }
-
-    if (!isset($class)) {
-      throw new PluginException(sprintf('The plugin (%s) did not specify an instance class.', $data_type));
+    // Pass remaining values from definition array to data definition.
+    foreach ($definition as $key => $value) {
+      if (!isset($data_definition[$key])) {
+        $data_definition[$key] = $value;
+      }
     }
-    return new $class($data_definition, $configuration['name'], $configuration['parent']);
+    return $data_definition;
   }
 
   /**
@@ -169,7 +163,11 @@ public function getDefinition($base_plugin_id, $exception_on_invalid = TRUE) {
       unset($definition['type']);
       $this->definitions[$type] = $definition;
     }
-    return $definition;
+    // Add type and default definition class.
+    return $definition + array(
+      'definition_class' => '\Drupal\Core\TypedData\DataDefinition',
+      'type' => $type,
+    );
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php b/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php
index 827363f..8b0da5e 100644
--- a/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php
+++ b/core/lib/Drupal/Core/Config/TypedConfigManagerInterface.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Plugin\Discovery\CachedDiscoveryInterface;
 use Drupal\Component\Plugin\PluginManagerInterface;
+use Drupal\Core\TypedData\DataDefinitionInterface;
 
 /**
  * Defines an interface for typed configuration manager.
@@ -36,7 +37,8 @@ public function get($name);
    *   instantiated.
    * @param array $configuration
    *   The plugin configuration array, i.e. an array with the following keys:
-   *   - data definition: The data definition array.
+   *   - data definition: The data definition object, i.e. an instance of
+   *     \Drupal\Core\TypedData\DataDefinitionInterface.
    *   - name: (optional) If a property or list item is to be created, the name
    *     of the property or the delta of the list item.
    *   - parent: (optional) If a property or list item is to be created, the
@@ -51,8 +53,8 @@ public function createInstance($data_type, array $configuration = array());
   /**
    * Creates a new typed configuration object instance.
    *
-   * @param array $definition
-   *   The data definition of the typed data object
+   * @param \Drupal\Core\TypedData\DataDefinitionInterface $definition
+   *   The data definition of the typed data object.
    * @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.
@@ -67,7 +69,26 @@ public function createInstance($data_type, array $configuration = array());
    * @return \Drupal\Core\Config\Schema\Element
    *   The instantiated typed data object.
    */
-  public function create(array $definition, $value = NULL, $name = NULL, $parent = NULL);
+  public function create(DataDefinitionInterface $definition, $value = NULL, $name = NULL, $parent = NULL);
+
+  /**
+   * Creates a new data definition object from a type definition array and
+   * actual configuration data. Since type definitions may contain variables
+   * to be replaced, we need the full data to create it.
+   *
+   * @param array $definition
+   *   The base type definition array, for which a data definition should be created.
+   * @param $value
+   *   Optional value of the configuraiton element.
+   * @param string $name
+   *   Optional name of the configuration element.
+   * @param object $parent
+   *   Optional parent element
+   *
+   * @return \Drupal\Core\TypedData\DataDefinitionInterface
+   *   A data definition for the given data type.
+   */
+  public function buildDataDefinition(array $definition, $value = NULL, $name = NULL, $parent = NULL);
 
   /**
    * Checks if the configuration schema with the given config name exists.
