diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index dfccfca1b8f..97bebeadfb3 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -12755,7 +12755,7 @@ namespace ts {
* @param node the expression whose contextual type will be returned.
* @returns the contextual type of an expression.
*/
- function getContextualType(node: Expression): Type {
+ function getContextualType(node: Expression): Type | undefined {
if (isInsideWithStatementBody(node)) {
// We cannot answer semantic questions within a with block, do not proceed any further
return undefined;
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 74670352c34..d89c7877da6 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -2528,7 +2528,7 @@ namespace ts {
getFullyQualifiedName(symbol: Symbol): string;
getAugmentedPropertiesOfType(type: Type): Symbol[];
getRootSymbols(symbol: Symbol): Symbol[];
- getContextualType(node: Expression): Type;
+ getContextualType(node: Expression): Type | undefined;
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature;
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts
index 09d1f2a248c..07b1e4448bd 100644
--- a/src/services/goToDefinition.ts
+++ b/src/services/goToDefinition.ts
@@ -85,17 +85,6 @@ namespace ts.GoToDefinition {
declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName));
}
- if (isJsxOpeningLikeElement(node.parent)) {
- // If there are errors when trying to figure out stateless component function, just return the first declaration
- // For example:
- // declare function /*firstSource*/MainButton(buttonProps: ButtonProps): JSX.Element;
- // declare function /*secondSource*/MainButton(linkProps: LinkProps): JSX.Element;
- // declare function /*thirdSource*/MainButton(props: ButtonProps | LinkProps): JSX.Element;
- // let opt = ; // Error - We get undefined for resolved signature indicating an error, then just return the first declaration
- const {symbolName, symbolKind, containerName} = getSymbolInfo(typeChecker, symbol, node);
- return [createDefinitionInfo(symbol.valueDeclaration, symbolKind, symbolName, containerName)];
- }
-
// If the current location we want to find its definition is in an object literal, try to get the contextual type for the
// object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
// For example
@@ -106,15 +95,9 @@ namespace ts.GoToDefinition {
// function Foo(arg: Props) {}
// Foo( { pr/*1*/op1: 10, prop2: true })
const element = getContainingObjectLiteralElement(node);
- if (element) {
- if (typeChecker.getContextualType(element.parent as Expression)) {
- const result: DefinitionInfo[] = [];
- const propertySymbols = getPropertySymbolsFromContextualType(typeChecker, element);
- for (const propertySymbol of propertySymbols) {
- result.push(...getDefinitionFromSymbol(typeChecker, propertySymbol, node));
- }
- return result;
- }
+ if (element && typeChecker.getContextualType(element.parent as Expression)) {
+ return flatMap(getPropertySymbolsFromContextualType(typeChecker, element), propertySymbol =>
+ getDefinitionFromSymbol(typeChecker, propertySymbol, node));
}
return getDefinitionFromSymbol(typeChecker, symbol, node);
}
diff --git a/tests/cases/fourslash/tsxGoToDefinitionClassInDifferentFile.ts b/tests/cases/fourslash/tsxGoToDefinitionClassInDifferentFile.ts
new file mode 100644
index 00000000000..f217e4096fc
--- /dev/null
+++ b/tests/cases/fourslash/tsxGoToDefinitionClassInDifferentFile.ts
@@ -0,0 +1,15 @@
+///
+
+// @jsx: preserve
+
+// @Filename: C.tsx
+////export default class C {}
+
+// @Filename: a.tsx
+////import /*def*/C from "./C";
+////const foo = *use*/C />;
+
+verify.noErrors();
+
+goTo.marker("use");
+verify.goToDefinitionIs("def");