mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Fix fallthrough and default in new switch-true narrowing (#55991)
This commit is contained in:
+31
-5
@@ -27456,11 +27456,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
type = narrowTypeBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
|
||||
}
|
||||
else if (expr.kind === SyntaxKind.TrueKeyword) {
|
||||
const clause = flow.switchStatement.caseBlock.clauses.find((_, index) => index === flow.clauseStart);
|
||||
const clauseExpression = clause && clause.kind === SyntaxKind.CaseClause ? clause.expression : undefined;
|
||||
if (clauseExpression) {
|
||||
type = narrowType(type, clauseExpression, /*assumeTrue*/ true);
|
||||
}
|
||||
type = narrowTypeBySwitchOnTrue(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd);
|
||||
}
|
||||
else {
|
||||
if (strictNullChecks) {
|
||||
@@ -28075,6 +28071,36 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return getUnionType(map(clauseWitnesses, text => text ? narrowTypeByTypeName(type, text) : neverType));
|
||||
}
|
||||
|
||||
function narrowTypeBySwitchOnTrue(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): Type {
|
||||
const defaultIndex = findIndex(switchStatement.caseBlock.clauses, clause => clause.kind === SyntaxKind.DefaultClause);
|
||||
const hasDefaultClause = clauseStart === clauseEnd || (defaultIndex >= clauseStart && defaultIndex < clauseEnd);
|
||||
|
||||
// First, narrow away all of the cases that preceded this set of cases.
|
||||
for (let i = 0; i < clauseStart; i++) {
|
||||
const clause = switchStatement.caseBlock.clauses[i];
|
||||
if (clause.kind === SyntaxKind.CaseClause) {
|
||||
type = narrowType(type, clause.expression, /*assumeTrue*/ false);
|
||||
}
|
||||
}
|
||||
|
||||
// If our current set has a default, then none the other cases were hit either.
|
||||
// There's no point in narrowing by the the other cases in the set, since we can
|
||||
// get here through other paths.
|
||||
if (hasDefaultClause) {
|
||||
for (let i = clauseEnd; i < switchStatement.caseBlock.clauses.length; i++) {
|
||||
const clause = switchStatement.caseBlock.clauses[i];
|
||||
if (clause.kind === SyntaxKind.CaseClause) {
|
||||
type = narrowType(type, clause.expression, /*assumeTrue*/ false);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Now, narrow based on the cases in this set.
|
||||
const clauses = switchStatement.caseBlock.clauses.slice(clauseStart, clauseEnd);
|
||||
return getUnionType(map(clauses, clause => clause.kind === SyntaxKind.CaseClause ? narrowType(type, clause.expression, /*assumeTrue*/ true) : neverType));
|
||||
}
|
||||
|
||||
function isMatchingConstructorReference(expr: Expression) {
|
||||
return (isPropertyAccessExpression(expr) && idText(expr.name) === "constructor" ||
|
||||
isElementAccessExpression(expr) && isStringLiteralLike(expr.argumentExpression) && expr.argumentExpression.text === "constructor") &&
|
||||
|
||||
Reference in New Issue
Block a user