diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 86dfb26a092..6160f4e4757 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1839,7 +1839,7 @@ namespace ts { if (symbol.flags & SymbolFlags.Variable) { const typeAnnotation = (symbol.valueDeclaration).type; if (typeAnnotation) { - return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); // TODO: GH#18217 + return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name)); } } } @@ -6865,11 +6865,7 @@ namespace ts { return obj.properties.some(property => { const name = property.name && getTextOfPropertyName(property.name); const expected = name === undefined ? undefined : getTypeOfPropertyOfType(contextualType, name); - if (expected && typeIsLiteralType(expected)) { - const actual = getTypeOfNode(property); - return !!actual && !isTypeIdenticalTo(actual, expected); - } - return false; + return !!expected && typeIsLiteralType(expected) && !isTypeIdenticalTo(getTypeOfNode(property), expected); }); } @@ -9841,7 +9837,7 @@ namespace ts { case SyntaxKind.Identifier: case SyntaxKind.QualifiedName: const symbol = getSymbolAtLocation(node); - return (symbol && getDeclaredTypeOfSymbol(symbol))!; // TODO: GH#18217 + return symbol ? getDeclaredTypeOfSymbol(symbol) : errorType; default: return errorType; } @@ -19414,7 +19410,7 @@ namespace ts { } const typeArgumentNodes: ReadonlyArray = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments || emptyArray : emptyArray; - const typeArguments = typeArgumentNodes.map(n => getTypeOfNode(n) || anyType); + const typeArguments = typeArgumentNodes.map(getTypeOfNode); while (typeArguments.length > typeParameters.length) { typeArguments.pop(); } @@ -27267,7 +27263,7 @@ namespace ts { grandParent.kind === SyntaxKind.ObjectBindingPattern && node === (parent).propertyName) { const typeOfPattern = getTypeOfNode(grandParent); - const propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (node).escapedText); + const propertyDeclaration = getPropertyOfType(typeOfPattern, (node).escapedText); if (propertyDeclaration) { return propertyDeclaration; @@ -27367,7 +27363,7 @@ namespace ts { if (isPartOfTypeNode(node)) { let typeFromTypeNode = getTypeFromTypeNode(node); - if (typeFromTypeNode && isExpressionWithTypeArgumentsInClassImplementsClause(node)) { + if (isExpressionWithTypeArgumentsInClassImplementsClause(node)) { const containingClass = getContainingClass(node)!; const classType = getTypeOfNode(containingClass) as InterfaceType; typeFromTypeNode = getTypeWithThisArgument(typeFromTypeNode, classType.thisType); @@ -27385,8 +27381,8 @@ namespace ts { // extends clause of a class. We handle that case here. const classNode = getContainingClass(node)!; const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classNode)) as InterfaceType; - const baseType = getBaseTypes(classType)[0]; - return baseType && getTypeWithThisArgument(baseType, classType.thisType); + const baseType = firstOrUndefined(getBaseTypes(classType)); + return baseType ? getTypeWithThisArgument(baseType, classType.thisType) : errorType; } if (isTypeDeclaration(node)) { diff --git a/src/harness/typeWriter.ts b/src/harness/typeWriter.ts index 72af0c7cde7..72ce3425cd8 100644 --- a/src/harness/typeWriter.ts +++ b/src/harness/typeWriter.ts @@ -83,8 +83,9 @@ class TypeWriterWalker { // Workaround to ensure we output 'C' instead of 'typeof C' for base class expressions // let type = this.checker.getTypeAtLocation(node); - const type = node.parent && ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) && this.checker.getTypeAtLocation(node.parent) || this.checker.getTypeAtLocation(node); - const typeString = type ? this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType) : "No type information available!"; + let type = ts.isExpressionWithTypeArgumentsInClassExtendsClause(node.parent) ? this.checker.getTypeAtLocation(node.parent) : undefined; + if (!type || type.flags & ts.TypeFlags.Any) type = this.checker.getTypeAtLocation(node); + const typeString = this.checker.typeToString(type, node.parent, ts.TypeFormatFlags.NoTruncation | ts.TypeFormatFlags.AllowUniqueESSymbolType); return { line: lineAndCharacter.line, syntaxKind: node.kind, diff --git a/tests/cases/fourslash/typeCheckAfterResolve.ts b/tests/cases/fourslash/typeCheckAfterResolve.ts index 388a02dac91..23c7409a629 100644 --- a/tests/cases/fourslash/typeCheckAfterResolve.ts +++ b/tests/cases/fourslash/typeCheckAfterResolve.ts @@ -11,7 +11,7 @@ goTo.eof(); edit.insertLine(""); // Attempt to resolve a symbol -verify.quickInfoAt("IPointRef", ""); // not found +verify.quickInfoAt("IPointRef", "any"); // not found // trigger typecheck after the partial resolve, we should see errors verify.errorExistsAfterMarker("IPointRef");