diff --git a/core/config/schema/core.data_types.schema.yml b/core/config/schema/core.data_types.schema.yml
index fb9aad1..81a4ced 100644
--- a/core/config/schema/core.data_types.schema.yml
+++ b/core/config/schema/core.data_types.schema.yml
@@ -78,6 +78,13 @@ color_hex:
   type: string
   label: 'Color'
 
+# Plugin ID are used to determine configuration schema. Plugin IDs can contain
+# derivative IDs that need to be removed.
+plugin_id:
+  type: string
+  label: 'Plugin'
+  schema_type_resolver: '/^[^:]*/'
+
 # Complex extended data types:
 
 # Mail text with subject and body parts.
diff --git a/core/lib/Drupal/Core/Config/TypedConfigManager.php b/core/lib/Drupal/Core/Config/TypedConfigManager.php
index c025a20..97e6acb 100644
--- a/core/lib/Drupal/Core/Config/TypedConfigManager.php
+++ b/core/lib/Drupal/Core/Config/TypedConfigManager.php
@@ -10,6 +10,8 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Config\Schema\ConfigSchemaDiscovery;
+use Drupal\Core\Config\Schema\Mapping;
+use Drupal\Core\Config\Schema\Sequence;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\TypedData\TypedDataManager;
 
@@ -90,7 +92,7 @@ public function buildDataDefinition(array $definition, $value, $name = NULL, $pa
       if (isset($name)) {
         $replace['%key'] = $name;
       }
-      $definition['type'] = $this->replaceName($definition['type'], $replace);
+      $definition['type'] = $this->replaceName($definition, $replace);
     }
     // Add default values from type definition.
     $definition += $this->getDefinition($definition['type']);
@@ -195,24 +197,34 @@ protected function getFallbackName($name) {
    * enclosed in square brackets like '[name]' and will follow the replacement
    * rules defined by the replaceVariable() method.
    *
-   * @param string $name
-   *   Configuration name with variables in square brackets.
+   * @param array $definition
+   *   The schema definition.
    * @param mixed $data
    *   Configuration data for the element.
    * @return string
    *   Configuration name with variables replaced.
    */
-  protected function replaceName($name, $data) {
-    if (preg_match_all("/\[(.*)\]/U", $name, $matches)) {
+  protected function replaceName(array $definition, $data) {
+    if (preg_match_all("/\[(.*)\]/U", $definition['type'], $matches)) {
       // Build our list of '[value]' => replacement.
       $replace = array();
+      if (isset($definition['base_type'])) {
+        $data_definition = $this->buildDataDefinition(
+          $this->getDefinition($definition['base_type'], FALSE),
+          $data
+        );
+        $schema = $this->create($data_definition, $data);
+      }
+      else {
+        $schema = NULL;
+      }
       foreach (array_combine($matches[0], $matches[1]) as $key => $value) {
-        $replace[$key] = $this->replaceVariable($value, $data);
+        $replace[$key] = $this->replaceVariable($value, $data, $schema);
       }
-      return strtr($name, $replace);
+      return strtr($definition['type'], $replace);
     }
     else {
-      return $name;
+      return $definition['type'];
     }
   }
 
@@ -237,11 +249,13 @@ protected function replaceName($name, $data) {
    *   Variable value to be replaced.
    * @param mixed $data
    *   Configuration data for the element.
+   * @param object $schema
+   *   The configuration schema object.
    *
    * @return string
    *   The replaced value if a replacement found or the original value if not.
    */
-  protected function replaceVariable($value, $data) {
+  protected function replaceVariable($value, $data, $schema) {
     $parts = explode('.', $value);
     // Process each value part, one at a time.
     while ($name = array_shift($parts)) {
@@ -251,13 +265,23 @@ protected function replaceVariable($value, $data) {
       }
       elseif (!$parts) {
         // If no more parts left, this is the final property.
+        if ($schema !== NULL) {
+          // If the schema for the value has a schema type resolver regular
+          // expression then use it to manipulate the value.
+          $defintion = $schema->get($name)->getDataDefinition()->toArray();
+          if (isset($defintion['schema_type_resolver'])) {
+            if (preg_match($defintion['schema_type_resolver'], (string)$data[$name], $matches)) {
+              return $matches[0];
+            }
+          }
+        }
         return (string)$data[$name];
       }
       else {
         // Get nested value and continue processing.
         if ($name == '%parent') {
-          // Switch replacement values with values from the parent.
-          $parent = $data['%parent'];
+          // Switch replacement values and schema with values from the parent.
+          $parent = $schema = $data['%parent'];
           $data = $parent->getValue();
           // The special %parent and %key values now need to point one level up.
           if ($new_parent = $parent->getParent()) {
diff --git a/core/modules/config/src/Tests/ConfigSchemaTest.php b/core/modules/config/src/Tests/ConfigSchemaTest.php
index 7401247..c7381fb 100644
--- a/core/modules/config/src/Tests/ConfigSchemaTest.php
+++ b/core/modules/config/src/Tests/ConfigSchemaTest.php
@@ -397,4 +397,21 @@ function testSchemaFallback() {
     $this->assertIdentical($definition, $definition2);
   }
 
+  /**
+   * Tests use of schema_type_resolver to determine schema..
+   */
+  function testSchemaTypeResolver() {
+    $tests = \Drupal::service('config.typed')->get('config_schema_test.plugin_types')->get('tests');
+    $definition = $tests[0]->getDataDefinition()->toArray();
+    $this->assertEqual($definition['type'], 'test.plugin_types.boolean');
+    $definition = $tests[1]->getDataDefinition()->toArray();
+    $this->assertEqual($definition['type'], 'test.plugin_types.boolean');
+
+    $tests = \Drupal::service('config.typed')->get('config_schema_test.plugin_types')->get('test_with_parents');
+    $definition = $tests[0]['settings']->getDataDefinition()->toArray();
+    $this->assertEqual($definition['type'], 'test_with_parents.plugin_types.boolean');
+    $definition = $tests[1]['settings']->getDataDefinition()->toArray();
+    $this->assertEqual($definition['type'], 'test_with_parents.plugin_types.boolean');
+  }
+
 }
diff --git a/core/modules/config/tests/config_schema_test/config/install/config_schema_test.plugin_types.yml b/core/modules/config/tests/config_schema_test/config/install/config_schema_test.plugin_types.yml
new file mode 100644
index 0000000..7241e8d
--- /dev/null
+++ b/core/modules/config/tests/config_schema_test/config/install/config_schema_test.plugin_types.yml
@@ -0,0 +1,16 @@
+tests:
+  -
+    plugin_id: boolean
+    value: TRUE
+  -
+    plugin_id: boolean:derivative
+    value: TRUE
+test_with_parents:
+  -
+    plugin_id: boolean
+    settings:
+      value: TRUE
+  -
+    plugin_id: boolean:derivative
+    settings:
+      value: TRUE
diff --git a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
index 34c6089..cc8f480 100644
--- a/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
+++ b/core/modules/config/tests/config_schema_test/config/schema/config_schema_test.schema.yml
@@ -149,3 +149,41 @@ config_schema_test.ignore:
     weight:
       type: integer
       label: 'Weight'
+
+config_schema_test.plugin_types:
+  type: mapping
+  mapping:
+    tests:
+      type: sequence
+      sequence:
+        - type: test.plugin_types.[plugin_id]
+          base_type: test.plugin_types
+    test_with_parents:
+      type: sequence
+      sequence:
+        - type: mapping
+          mapping:
+            plugin_id:
+              type: plugin_id
+            settings:
+              type: test_with_parents.plugin_types.[%parent.plugin_id]
+
+test.plugin_types:
+  type: mapping
+  mapping:
+    plugin_id:
+      type: plugin_id
+
+test.plugin_types.boolean:
+  type: mapping
+  mapping:
+    plugin_id:
+      type: plugin_id
+    value:
+      type: boolean
+
+test_with_parents.plugin_types.boolean:
+  type: mapping
+  mapping:
+    value:
+      type: boolean
