Skip to content

Commit 0ffde2d

Browse files
committed
Reduce types before checking if they are never
When types are checked if they are `never` by their `TypeFlags`, they must first be reduced, because intersection types of object-like types which reduce to `never` don't have `TypeFlags.Never`. See microsoft#36696 for details. When a function is declared to return such type and it doesn't contain any return statement or it only contains return statements without expression, the error messages are incorrect as the checker sees its return type as non-`never`. This commit takes into account that intersection types potentially reduces to `never` and improves error messages.
1 parent efe5e3d commit 0ffde2d

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

src/compiler/checker.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -32140,7 +32140,8 @@ namespace ts {
3214032140
}
3214132141

3214232142
const functionFlags = getFunctionFlags(func);
32143-
const type = returnType && unwrapReturnType(returnType, functionFlags);
32143+
const unwrappedType = returnType && unwrapReturnType(returnType, functionFlags);
32144+
const type = unwrappedType && getReducedType(unwrappedType);
3214432145

3214532146
// Functions with with an explicitly specified 'void' or 'any' return type don't need any return expressions.
3214632147
if (type && maybeTypeOfKind(type, TypeFlags.Any | TypeFlags.Void)) {
@@ -32157,7 +32158,9 @@ namespace ts {
3215732158
const errorNode = getEffectiveReturnTypeNode(func) || func;
3215832159

3215932160
if (type && type.flags & TypeFlags.Never) {
32160-
error(errorNode, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
32161+
const elaboration = elaborateNeverIntersection(/*errorInfo*/ undefined, unwrappedType);
32162+
const diagnostic = chainDiagnosticMessages(elaboration, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
32163+
diagnostics.add(createDiagnosticForNodeFromMessageChain(errorNode, diagnostic));
3216132164
}
3216232165
else if (type && !hasExplicitReturn) {
3216332166
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
@@ -38219,7 +38222,7 @@ namespace ts {
3821938222
const signature = getSignatureFromDeclaration(container);
3822038223
const returnType = getReturnTypeOfSignature(signature);
3822138224
const functionFlags = getFunctionFlags(container);
38222-
if (strictNullChecks || node.expression || returnType.flags & TypeFlags.Never) {
38225+
if (strictNullChecks || node.expression || returnType.flags & (TypeFlags.Never | TypeFlags.Intersection)) {
3822338226
const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType;
3822438227
if (container.kind === SyntaxKind.SetAccessor) {
3822538228
if (node.expression) {

0 commit comments

Comments
 (0)