diff --git a/pages/docs/changelog.md b/pages/docs/changelog.md
index 138ad9b2fae4140e8d172635202a089d12d7e4b6..1fcc26bc7052a700a13b934b0e4c2ee32bb2b6d9 100644
--- a/pages/docs/changelog.md
+++ b/pages/docs/changelog.md
@@ -7,6 +7,7 @@
 ### Development Changes
 
 - Bugfix: "error: variable handler is already defined" when using multiple protocols [#58](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/58)
+- Bugfix: Inherited components of a type can not be chosen as port targets [#59](https://git-st.inf.tu-dresden.de/jastadd/ragconnect/-/issues/59)
 
 ## 1.0.0
 
diff --git a/ragconnect.base/src/main/jastadd/NameResolution.jrag b/ragconnect.base/src/main/jastadd/NameResolution.jrag
index e470430d8f5d355cd90d4e79503ee431de994a18..6e7c74576f1a6ef68d045733cc59a6b6368a2246 100644
--- a/ragconnect.base/src/main/jastadd/NameResolution.jrag
+++ b/ragconnect.base/src/main/jastadd/NameResolution.jrag
@@ -91,7 +91,7 @@ aspect RagConnectNameResolution {
     String childTypeName = id.substring(dotIndex + 1);
     TypeDecl type = program().resolveTypeDecl(parentTypeName);
     // iterate over components and find the matching typeComponent
-    for (Component comp : type.getComponentList()) {
+    for (Component comp : type.allComponentsAsOwnedByMe()) {
       if (comp.isTypeComponent() && comp.getName().equals(childTypeName)) {
         return comp.asTypeComponent();
       }
@@ -114,7 +114,7 @@ aspect RagConnectNameResolution {
     String childTypeName = id.substring(dotIndex + 1);
     TypeDecl type = program().resolveTypeDecl(parentTypeName);
     // iterate over components and find the matching typeComponent
-    for (Component comp : type.getComponentList()) {
+    for (Component comp : type.allComponentsAsOwnedByMe()) {
       if (comp.getName().equals(childTypeName)) {
         return comp;
       }
@@ -138,7 +138,7 @@ aspect RagConnectNameResolution {
     String tokenName = id.substring(dotIndex + 1);
     TypeDecl type = program().resolveTypeDecl(typeName);
     // iterate over components and find the matching tokenComponent
-    for (Component comp : type.getComponentList()) {
+    for (Component comp : type.allComponentsAsOwnedByMe()) {
       if (comp.isTokenComponent() && comp.getName().equals(tokenName)) {
         return comp.asTokenComponent();
       }
@@ -175,10 +175,60 @@ aspect RagConnectNameResolution {
     }
     return null;
   }
+}
 
+aspect RelastNameResolution {
   syn boolean Role.matches(String typeName, String roleName) = false;
   eq NavigableRole.matches(String typeName, String roleName) {
     return getType().getName().equals(typeName) && getName().equals(roleName);
   }
 
+  /** Returns all components including inherited ones */
+  syn List<Component> TypeDecl.allComponents() {
+    List<Component> result = new ArrayList<>();
+    getComponentList().forEach(result::add);
+    if (hasSuperType()) {
+      mergeComponentLists(result, getSuperType().allComponents());
+    }
+    return result;
+  }
+
+  /** Returns same as allComponents() but for each component the containingTypeDecl will compute to this component */
+  syn nta JastAddList<Component> TypeDecl.allComponentsAsOwnedByMe() {
+    JastAddList<Component> result = new JastAddList<>();
+    for (Component comp : allComponents()) {
+      result.add(comp.treeCopy());
+    }
+    return result;
+  }
+
+  public static void TypeDecl.mergeComponentLists(List<Component> subTypeResult, List<Component> superTypeResult) {
+    for (int i = superTypeResult.size() - 1; i >= 0; i--) {
+      Component superTypeComponent = superTypeResult.get(i);
+      if (subTypeResult.stream().noneMatch(subTypeComponent -> subTypeComponent.matches(superTypeComponent))) {
+        subTypeResult.add(0, superTypeComponent);
+      }
+    }
+  }
+
+  syn boolean Component.matches(Component other) = false;
+  eq TokenComponent.matches(Component other) {
+    if (!other.isTokenComponent()) { return false; }
+    return getName().equals(other.getName()) && getJavaTypeUse().prettyPrint().equals(other.asTokenComponent().getJavaTypeUse().prettyPrint());
+  }
+  eq TypeComponent.matches(Component other) {
+    return getName().equals(other.getName()) && getTypeDecl().equals(other.asTypeComponent().getTypeDecl());
+  }
+  eq NormalComponent.matches(Component other) {
+    if (!other.isTypeComponent() || !other.asTypeComponent().isNormalComponent()) { return false; }
+    return super.matches(other);
+  }
+  eq ListComponent.matches(Component other) {
+    if (!other.isTypeComponent() || !other.asTypeComponent().isListComponent()) { return false; }
+    return super.matches(other);
+  }
+  eq OptComponent.matches(Component other) {
+    if (!other.isTypeComponent() || !other.asTypeComponent().isOptComponent()) { return false; }
+    return super.matches(other);
+  }
 }
diff --git a/ragconnect.tests/src/test/01-input/passing/README.md b/ragconnect.tests/src/test/01-input/passing/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..15afc42285d80e7e205777af6333162100cb36dd
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/passing/README.md
@@ -0,0 +1,4 @@
+# Passing
+
+This directory contains use case for RagConnect, that just need to pass compiling (no dedicated Java test).
+
diff --git a/ragconnect.tests/src/test/01-input/passing/inheritance/Test.connect b/ragconnect.tests/src/test/01-input/passing/inheritance/Test.connect
new file mode 100644
index 0000000000000000000000000000000000000000..3b4690cd05838159de6e5c9be0e47808ca25f9ab
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/passing/inheritance/Test.connect
@@ -0,0 +1,18 @@
+// both directions for SpecialA1
+send SpecialA1.Input ;
+receive SpecialA1.Input ;
+
+send SpecialA1.Many ;
+receive SpecialA1.Many ;
+
+send SpecialA1.Maybe ;
+receive SpecialA1.Maybe ;
+
+send SpecialA1.B ;
+receive SpecialA1.B ;
+
+// only one direction for SpecialA2
+send SpecialA2.Input ;
+send SpecialA2.Many ;
+send SpecialA2.Maybe ;
+send SpecialA2.B ;
diff --git a/ragconnect.tests/src/test/01-input/passing/inheritance/Test.relast b/ragconnect.tests/src/test/01-input/passing/inheritance/Test.relast
new file mode 100644
index 0000000000000000000000000000000000000000..7de55c8642cbb307c615e7abe78833f7e7ff1a6c
--- /dev/null
+++ b/ragconnect.tests/src/test/01-input/passing/inheritance/Test.relast
@@ -0,0 +1,5 @@
+Root ::= A ;
+A ::= <Input:String> Many:B* [Maybe:B] B ;
+SpecialA1 : A ;
+SpecialA2 : A ;
+B ::= ;
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractCompilerTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractCompilerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..002f9815f9eb09b8b41d533c9f01d6dcc5f0e98f
--- /dev/null
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/AbstractCompilerTest.java
@@ -0,0 +1,61 @@
+package org.jastadd.ragconnect.tests;
+
+import org.jastadd.ragconnect.tests.utils.TestUtils;
+import org.junit.jupiter.api.BeforeEach;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.jastadd.ragconnect.tests.utils.TestUtils.readFile;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * TODO: Add description.
+ *
+ * @author rschoene - Initial contribution
+ */
+public abstract class AbstractCompilerTest extends RagConnectTest {
+
+  protected abstract String getDirectoryName();
+
+  protected String getOutputDirectory() {
+    return TestUtils.OUTPUT_DIRECTORY_PREFIX + getDirectoryName();
+  }
+
+  protected abstract String getDefaultGrammarName();
+
+  @BeforeEach
+  public void ensureOutputDirectory() {
+    File outputDirectory = new File(getOutputDirectory());
+    assertTrue((outputDirectory.exists() && outputDirectory.isDirectory()) || outputDirectory.mkdir());
+  }
+
+  protected Path test(String inputDirectoryName, int expectedReturnValue, String rootNode, String... connectNames) throws IOException {
+    String grammarFile = Paths.get(inputDirectoryName, getDefaultGrammarName() + ".relast").toString();
+    List<String> connectFiles = Arrays.stream(connectNames)
+            .map(connectName -> Paths.get(inputDirectoryName,connectName + ".connect").toString())
+            .collect(Collectors.toList());
+    return TestUtils.runCompiler(grammarFile, connectFiles, rootNode,
+            getDirectoryName(), expectedReturnValue);
+  }
+
+  protected void testAndCompare(String inputDirectoryName, String expectedName, String rootNode, String... connectNames) throws IOException {
+    Path outPath = test(inputDirectoryName, 1, rootNode, connectNames);
+
+    final String startOfErrorsPattern = "Errors:\n";
+    String out = readFile(outPath, Charset.defaultCharset());
+    assertThat(out).contains(startOfErrorsPattern);
+    out = out.substring(out.indexOf(startOfErrorsPattern) + startOfErrorsPattern.length());
+
+    TestUtils.assertLinesMatch(getDirectoryName(), expectedName, out);
+
+    logger.info("ragconnect for " + expectedName + " returned:\n{}", out);
+  }
+}
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ErrorsTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ErrorsTest.java
index 4853b6a7e62f6e71878b37700a72fe2515655200..7f7e0cb2fbbaba2f6ce2995d9866ba10142e2039 100644
--- a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ErrorsTest.java
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/ErrorsTest.java
@@ -1,65 +1,33 @@
 package org.jastadd.ragconnect.tests;
 
-import org.jastadd.ragconnect.tests.utils.TestUtils;
-import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
 
-import java.io.File;
 import java.io.IOException;
-import java.nio.charset.Charset;
-import java.nio.file.Path;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.jastadd.ragconnect.tests.utils.TestUtils.readFile;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
  * Test error messages.
  *
  * @author rschoene - Initial contribution
  */
-public class ErrorsTest extends RagConnectTest {
-
-  private static final String ERROR_DIRECTORY = "errors/";
-  private static final String OUTPUT_DIRECTORY = TestUtils.OUTPUT_DIRECTORY_PREFIX + ERROR_DIRECTORY;
+public class ErrorsTest extends AbstractCompilerTest {
 
-  private static final String DEFAULT_GRAMMAR_NAME = "Errors";
+  @Override
+  protected String getDirectoryName() {
+    return "errors";
+  }
 
-  @BeforeAll
-  public static void createOutputDirectory() {
-    File outputDirectory = new File(OUTPUT_DIRECTORY);
-    assertTrue((outputDirectory.exists() && outputDirectory.isDirectory()) || outputDirectory.mkdir());
+  @Override
+  protected String getDefaultGrammarName() {
+    return "Errors";
   }
 
   @Test
   void testStandardErrors() throws IOException {
-    test("Standard", "A", "Standard");
+    testAndCompare(getDirectoryName(), "Standard", "A", "Standard");
   }
 
   @Test
   void testTwoPartsErrors() throws IOException {
-    test("Part", "A", "Part1", "Part2");
+    testAndCompare(getDirectoryName(), "Part", "A", "Part1", "Part2");
   }
-
-  @SuppressWarnings("SameParameterValue")
-  private void test(String expectedName, String rootNode, String... connectNames) throws IOException {
-    String grammarFile = ERROR_DIRECTORY + DEFAULT_GRAMMAR_NAME + ".relast";
-    List<String> connectFiles = Arrays.stream(connectNames)
-        .map(connectName -> ERROR_DIRECTORY + connectName + ".connect")
-        .collect(Collectors.toList());
-    Path outPath = TestUtils.runCompiler(grammarFile, connectFiles, rootNode, ERROR_DIRECTORY, 1);
-
-    final String startOfErrorsPattern = "Errors:\n";
-    String out = readFile(outPath, Charset.defaultCharset());
-    assertThat(out).contains(startOfErrorsPattern);
-    out = out.substring(out.indexOf(startOfErrorsPattern) + startOfErrorsPattern.length());
-
-    TestUtils.assertLinesMatch(ERROR_DIRECTORY, expectedName, out);
-
-    logger.info("ragconnect for " + expectedName + " returned:\n{}", out);
-  }
-
 }
diff --git a/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/PassingTest.java b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/PassingTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5829c21d41f8ee0601a5218c33bb3d7165ae457b
--- /dev/null
+++ b/ragconnect.tests/src/test/java/org/jastadd/ragconnect/tests/PassingTest.java
@@ -0,0 +1,33 @@
+package org.jastadd.ragconnect.tests;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.nio.file.Paths;
+
+/**
+ * Use cases that just need to compile.
+ *
+ * @author rschoene - Initial contribution
+ */
+public class PassingTest extends AbstractCompilerTest {
+  @Override
+  protected String getDirectoryName() {
+    return "passing";
+  }
+
+  @Override
+  protected String getDefaultGrammarName() {
+    return "Test";
+  }
+
+  protected void run(String inputDirectoryName, String rootNode) throws IOException {
+    super.test(Paths.get("passing", inputDirectoryName).toString(),
+            0, rootNode, getDefaultGrammarName());
+  }
+
+  @Test
+  public void testInheritance() throws IOException {
+    run("inheritance", "Root");
+  }
+}