Skip to content

Commit 436339d

Browse files
committed
Use declared type for references in unreachable code
1 parent 5a180ba commit 436339d

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,7 @@ namespace ts {
671671
const silentNeverType = createIntrinsicType(TypeFlags.Never, "never");
672672
const nonInferrableType = createIntrinsicType(TypeFlags.Never, "never", ObjectFlags.NonInferrableType);
673673
const implicitNeverType = createIntrinsicType(TypeFlags.Never, "never");
674+
const unreachableNeverType = createIntrinsicType(TypeFlags.Never, "never");
674675
const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object");
675676
const stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]);
676677
const keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType;
@@ -17008,7 +17009,7 @@ namespace ts {
1700817009
// on empty arrays are possible without implicit any errors and new element types can be inferred without
1700917010
// type mismatch errors.
1701017011
const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType);
17011-
if (reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
17012+
if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
1701217013
return declaredType;
1701317014
}
1701417015
return resultType;
@@ -17144,8 +17145,11 @@ namespace ts {
1714417145
// Assignments only narrow the computed type if the declared type is a union type. Thus, we
1714517146
// only need to evaluate the assigned type if the declared type is a union type.
1714617147
if (isMatchingReference(reference, node)) {
17148+
const flowType = getTypeAtFlowNode(flow.antecedent);
17149+
if (flowType === unreachableNeverType) {
17150+
return flowType;
17151+
}
1714717152
if (getAssignmentTargetKind(node) === AssignmentKind.Compound) {
17148-
const flowType = getTypeAtFlowNode(flow.antecedent);
1714917153
return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType));
1715017154
}
1715117155
if (declaredType === autoType || declaredType === autoArrayType) {
@@ -17165,12 +17169,16 @@ namespace ts {
1716517169
// reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case,
1716617170
// return the declared type.
1716717171
if (containsMatchingReference(reference, node)) {
17172+
const flowType = getTypeAtFlowNode(flow.antecedent);
17173+
if (flowType === unreachableNeverType) {
17174+
return flowType;
17175+
}
1716817176
// A matching dotted name might also be an expando property on a function *expression*,
1716917177
// in which case we continue control flow analysis back to the function's declaration
1717017178
if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConst(node))) {
1717117179
const init = getDeclaredExpandoInitializer(node);
1717217180
if (init && (init.kind === SyntaxKind.FunctionExpression || init.kind === SyntaxKind.ArrowFunction)) {
17173-
return getTypeAtFlowNode(flow.antecedent);
17181+
return flowType;
1717417182
}
1717517183
}
1717617184
return declaredType;
@@ -17209,7 +17217,7 @@ namespace ts {
1720917217
return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType));
1721017218
}
1721117219
if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
17212-
return neverType;
17220+
return unreachableNeverType;
1721317221
}
1721417222
}
1721517223
return undefined;

0 commit comments

Comments
 (0)