diff --git a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
index 8819fe3..a846a6e 100644
--- a/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
+++ b/core/modules/link/src/Plugin/Field/FieldFormatter/LinkFormatter.php
@@ -241,9 +241,14 @@ public function viewElements(FieldItemListInterface $items) {
    *   An Url object.
    */
   protected function buildUrl(LinkItemInterface $item) {
+    $uri = $item->uri;
+    if (parse_url($uri, PHP_URL_SCHEME) === 'user-path') {
+      $uri = substr($uri, 12);
+    }
+
     // @todo Consider updating the usage of the path validator with whatever
     // gets added in https://www.drupal.org/node/2405551.
-    $url = $this->pathValidator->getUrlIfValidWithoutAccessCheck($item->uri) ?: Url::fromRoute('<none>');
+    $url = $this->pathValidator->getUrlIfValidWithoutAccessCheck($uri) ?: Url::fromRoute('<none>');
 
     $settings = $this->getSettings();
     $options = $item->options;
diff --git a/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
index d5c1fec..8ab89fb 100644
--- a/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
+++ b/core/modules/link/src/Plugin/Field/FieldType/LinkItem.php
@@ -44,9 +44,7 @@ public static function defaultFieldSettings() {
    * {@inheritdoc}
    */
   public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
-    // @todo Change the type from 'string' to 'uri':
-    //   https://www.drupal.org/node/2412509.
-    $properties['uri'] = DataDefinition::create('string')
+    $properties['uri'] = DataDefinition::create('uri')
       ->setLabel(t('URI'));
 
     $properties['title'] = DataDefinition::create('string')
@@ -154,7 +152,11 @@ public function isEmpty() {
    */
   public function isExternal() {
     // External links don't resolve to a route.
-    $url = \Drupal::pathValidator()->getUrlIfValid($this->uri);
+    $uri = $this->uri;
+    if (parse_url($uri, PHP_URL_SCHEME) === 'user-path') {
+      $uri = substr($uri, 12);
+    }
+    $url = \Drupal::pathValidator()->getUrlIfValid($uri);
     return $url->isExternal();
   }
 
@@ -171,7 +173,11 @@ public static function mainPropertyName() {
    * @return \Drupal\Core\Url
    */
   public function getUrl() {
-    return \Drupal::pathValidator()->getUrlIfValidWithoutAccessCheck($this->uri);
+    $uri = $this->uri;
+    if (parse_url($uri, PHP_URL_SCHEME) === 'user-path') {
+      $uri = substr($uri, 12);
+    }
+    return \Drupal::pathValidator()->getUrlIfValidWithoutAccessCheck($uri);
   }
 
 
diff --git a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
index 7768efe..a055a3b 100644
--- a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
+++ b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
@@ -43,7 +43,11 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
 
     $default_url_value = NULL;
     if (isset($items[$delta]->uri)) {
-      if ($url = \Drupal::pathValidator()->getUrlIfValid($items[$delta]->uri)) {
+      $uri = $items[$delta]->uri;
+      if (parse_url($uri, PHP_URL_SCHEME) === 'user-path') {
+        $uri = substr($uri, 12);
+      }
+      if ($url = \Drupal::pathValidator()->getUrlIfValid($uri)) {
         $url->setOptions($items[$delta]->options ?: []);
         $url_string = $url->toString();
         $default_url_value = $url->isRouted() ? Unicode::substr($url_string, strlen(base_path())) : $url_string;
@@ -202,16 +206,12 @@ public function validateTitle(&$element, FormStateInterface $form_state, $form)
   public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
     foreach ($values as &$value) {
       if (!empty($value['uri'])) {
-        $url = \Drupal::pathValidator()->getUrlIfValid($value['uri']);
-        if (!$url) {
-          return $values;
+        $scheme = parse_url($value['uri'], PHP_URL_SCHEME);
+        if (!$scheme) {
+          $value['uri'] = 'user-path://' . $value['uri'];
         }
 
         $value += ['options' => []];
-        // Reset the URL value to contain only the path.
-        if (!$url->isExternal() && $this->supportsInternalLinks()) {
-          $value['uri'] = substr($url->toString(), strlen(\Drupal::request()->getBasePath() . '/'));
-        }
       }
     }
     return $values;
diff --git a/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php b/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php
index 8ae29b2..d448add 100644
--- a/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php
+++ b/core/modules/link/src/Plugin/Validation/Constraint/LinkTypeConstraint.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\link\Plugin\Validation\Constraint;
 
+use Drupal\Core\Url;
 use Drupal\link\LinkItemInterface;
 use Symfony\Component\Validator\Constraint;
 use Symfony\Component\Validator\ConstraintValidatorInterface;
@@ -53,12 +54,19 @@ public function validate($value, Constraint $constraint) {
       $link_item = $value;
       $link_type = $link_item->getFieldDefinition()->getSetting('link_type');
       $url_string = $link_item->uri;
+      $scheme = parse_url($url_string, PHP_URL_SCHEME);
+      if ($scheme === 'user-path') {
+        $url_string = substr($url_string, 12);
+      }
       // Validate the url property.
-      if ($url_string !== '') {
+      if (($scheme === 'user-path' || $scheme === 'base') && !($link_type & LinkItemInterface::LINK_INTERNAL)) {
+        $url_is_valid = FALSE;
+      }
+      elseif ($url_string !== '') {
         if ($url = \Drupal::pathValidator()->getUrlIfValid($url_string)) {
           $url_is_valid = (bool) $url;
 
-          if ($url->isExternal() && !($link_type & LinkItemInterface::LINK_EXTERNAL)) {
+          if ($url_is_valid && $url->isExternal() && !($link_type & LinkItemInterface::LINK_EXTERNAL)) {
             $url_is_valid = FALSE;
           }
         }
diff --git a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
index 27202ba..ca43c17 100644
--- a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
+++ b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php
@@ -61,7 +61,7 @@ public function testShortcutLinkAdd() {
       $this->assertResponse(200);
       $saved_set = ShortcutSet::load($set->id());
       $paths = $this->getShortcutInformation($saved_set, 'link');
-      $test_path = $test_path != '<front>' ? $test_path : '';
+      $test_path = $test_path != '<front>' ? 'user-path://' . $test_path : '';
       $this->assertTrue(in_array($test_path, $paths), 'Shortcut created: ' . $test_path);
       $this->assertLink($title, 0, String::format('Shortcut link %url found on the page.', ['%url' => $test_path]));
     }
