Apply formatting fixes

This commit is contained in:
copilot-swe-agent[bot] 2025-07-23 21:10:06 +00:00
parent 5d94666678
commit 7f0a0e542b

View File

@ -29380,59 +29380,59 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return undefined;
}
function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) {
// As long as the computed type is a subset of the declared type, we use the full declared type to detect
// a discriminant property. In cases where the computed type isn't a subset, e.g because of a preceding type
// predicate narrowing, we use the actual computed type.
if (declaredType.flags & TypeFlags.Union || computedType.flags & TypeFlags.Union) {
const access = getCandidateDiscriminantPropertyAccess(expr);
if (access) {
const name = getAccessedPropertyName(access);
if (name) {
const type = declaredType.flags & TypeFlags.Union && isTypeSubsetOf(computedType, declaredType) ? declaredType : computedType;
if (isDiscriminantProperty(type, name)) {
return access;
}
}
}
}
// Fix for #23572: Allow discriminant property narrowing for non-union types
// This enables narrowing to never when all possibilities are eliminated
else {
const access = getCandidateDiscriminantPropertyAccess(expr);
if (access) {
const name = getAccessedPropertyName(access);
if (name) {
// For non-union types, check if the property exists and has a literal type
const type = declaredType.flags & TypeFlags.Union && isTypeSubsetOf(computedType, declaredType) ? declaredType : computedType;
const propType = getTypeOfPropertyOfType(type, name);
if (propType && isUnitLikeType(propType)) {
return access;
}
}
}
}
return undefined;
function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) {
// As long as the computed type is a subset of the declared type, we use the full declared type to detect
// a discriminant property. In cases where the computed type isn't a subset, e.g because of a preceding type
// predicate narrowing, we use the actual computed type.
if (declaredType.flags & TypeFlags.Union || computedType.flags & TypeFlags.Union) {
const access = getCandidateDiscriminantPropertyAccess(expr);
if (access) {
const name = getAccessedPropertyName(access);
if (name) {
const type = declaredType.flags & TypeFlags.Union && isTypeSubsetOf(computedType, declaredType) ? declaredType : computedType;
if (isDiscriminantProperty(type, name)) {
return access;
}
}
}
}
// Fix for #23572: Allow discriminant property narrowing for non-union types
// This enables narrowing to never when all possibilities are eliminated
else {
const access = getCandidateDiscriminantPropertyAccess(expr);
if (access) {
const name = getAccessedPropertyName(access);
if (name) {
// For non-union types, check if the property exists and has a literal type
const type = declaredType.flags & TypeFlags.Union && isTypeSubsetOf(computedType, declaredType) ? declaredType : computedType;
const propType = getTypeOfPropertyOfType(type, name);
if (propType && isUnitLikeType(propType)) {
return access;
}
}
}
}
return undefined;
}
function narrowTypeByDiscriminant(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, narrowType: (t: Type) => Type): Type {
const propName = getAccessedPropertyName(access);
if (propName === undefined) {
return type;
}
const optionalChain = isOptionalChain(access);
const removeNullable = strictNullChecks && (optionalChain || isNonNullAccess(access)) && maybeTypeOfKind(type, TypeFlags.Nullable);
let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, propName);
if (!propType) {
return type;
}
propType = removeNullable && optionalChain ? getOptionalType(propType) : propType;
const narrowedPropType = narrowType(propType);
return filterType(type, t => {
const discriminantType = getTypeOfPropertyOrIndexSignatureOfType(t, propName) || unknownType;
const result = !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType);
return result;
});
function narrowTypeByDiscriminant(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, narrowType: (t: Type) => Type): Type {
const propName = getAccessedPropertyName(access);
if (propName === undefined) {
return type;
}
const optionalChain = isOptionalChain(access);
const removeNullable = strictNullChecks && (optionalChain || isNonNullAccess(access)) && maybeTypeOfKind(type, TypeFlags.Nullable);
let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, propName);
if (!propType) {
return type;
}
propType = removeNullable && optionalChain ? getOptionalType(propType) : propType;
const narrowedPropType = narrowType(propType);
return filterType(type, t => {
const discriminantType = getTypeOfPropertyOrIndexSignatureOfType(t, propName) || unknownType;
const result = !(discriminantType.flags & TypeFlags.Never) && !(narrowedPropType.flags & TypeFlags.Never) && areTypesComparable(narrowedPropType, discriminantType);
return result;
});
}
function narrowTypeByDiscriminantProperty(type: Type, access: AccessExpression | BindingElement | ParameterDeclaration, operator: SyntaxKind, value: Expression, assumeTrue: boolean) {
@ -29635,43 +29635,43 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return removeNullable ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
}
function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
if (type.flags & TypeFlags.Any) {
return type;
}
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
const valueType = getTypeOfExpression(value);
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
if (valueType.flags & TypeFlags.Nullable) {
if (!strictNullChecks) {
return type;
}
const facts = doubleEquals ?
assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull :
valueType.flags & TypeFlags.Null ?
assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
return getAdjustedTypeWithFacts(type, facts);
}
if (assumeTrue) {
if (!doubleEquals && (type.flags & TypeFlags.Unknown || someType(type, isEmptyAnonymousObjectType))) {
if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || isEmptyAnonymousObjectType(valueType)) {
return valueType;
}
if (valueType.flags & TypeFlags.Object) {
return nonPrimitiveType;
}
}
const filteredType = filterType(type, t => areTypesComparable(t, valueType) || doubleEquals && isCoercibleUnderDoubleEquals(t, valueType));
return replacePrimitivesWithLiterals(filteredType, valueType);
}
if (isUnitType(valueType)) {
const result = filterType(type, t => !(isUnitLikeType(t) && areTypesComparable(t, valueType)));
return result;
}
return type;
function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type {
if (type.flags & TypeFlags.Any) {
return type;
}
if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) {
assumeTrue = !assumeTrue;
}
const valueType = getTypeOfExpression(value);
const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken;
if (valueType.flags & TypeFlags.Nullable) {
if (!strictNullChecks) {
return type;
}
const facts = doubleEquals ?
assumeTrue ? TypeFacts.EQUndefinedOrNull : TypeFacts.NEUndefinedOrNull :
valueType.flags & TypeFlags.Null ?
assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull :
assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined;
return getAdjustedTypeWithFacts(type, facts);
}
if (assumeTrue) {
if (!doubleEquals && (type.flags & TypeFlags.Unknown || someType(type, isEmptyAnonymousObjectType))) {
if (valueType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || isEmptyAnonymousObjectType(valueType)) {
return valueType;
}
if (valueType.flags & TypeFlags.Object) {
return nonPrimitiveType;
}
}
const filteredType = filterType(type, t => areTypesComparable(t, valueType) || doubleEquals && isCoercibleUnderDoubleEquals(t, valueType));
return replacePrimitivesWithLiterals(filteredType, valueType);
}
if (isUnitType(valueType)) {
const result = filterType(type, t => !(isUnitLikeType(t) && areTypesComparable(t, valueType)));
return result;
}
return type;
}
function narrowTypeByTypeof(type: Type, typeOfExpr: TypeOfExpression, operator: SyntaxKind, literal: LiteralExpression, assumeTrue: boolean): Type {
@ -39268,33 +39268,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return links.isExhaustive;
}
function computeExhaustiveSwitchStatement(node: SwitchStatement): boolean {
if (node.expression.kind === SyntaxKind.TypeOfExpression) {
const witnesses = getSwitchClauseTypeOfWitnesses(node);
if (!witnesses) {
return false;
}
const operandConstraint = getBaseConstraintOrType(checkExpressionCached((node.expression as TypeOfExpression).expression));
// Get the not-equal flags for all handled cases.
const notEqualFacts = getNotEqualFactsFromTypeofSwitch(0, 0, witnesses);
if (operandConstraint.flags & TypeFlags.AnyOrUnknown) {
// We special case the top types to be exhaustive when all cases are handled.
return (TypeFacts.AllTypeofNE & notEqualFacts) === TypeFacts.AllTypeofNE;
}
// A missing not-equal flag indicates that the type wasn't handled by some case.
return !someType(operandConstraint, t => getTypeFacts(t, notEqualFacts) === notEqualFacts);
}
const type = getBaseConstraintOrType(checkExpressionCached(node.expression));
if (!isLiteralType(type)) {
return false;
}
const switchTypes = getSwitchClauseTypes(node);
if (!switchTypes.length || some(switchTypes, isNeitherUnitTypeNorNever)) {
return false;
}
const mappedType = mapType(type, getRegularTypeOfLiteralType);
const result = eachTypeContainedIn(mappedType, switchTypes);
return result;
function computeExhaustiveSwitchStatement(node: SwitchStatement): boolean {
if (node.expression.kind === SyntaxKind.TypeOfExpression) {
const witnesses = getSwitchClauseTypeOfWitnesses(node);
if (!witnesses) {
return false;
}
const operandConstraint = getBaseConstraintOrType(checkExpressionCached((node.expression as TypeOfExpression).expression));
// Get the not-equal flags for all handled cases.
const notEqualFacts = getNotEqualFactsFromTypeofSwitch(0, 0, witnesses);
if (operandConstraint.flags & TypeFlags.AnyOrUnknown) {
// We special case the top types to be exhaustive when all cases are handled.
return (TypeFacts.AllTypeofNE & notEqualFacts) === TypeFacts.AllTypeofNE;
}
// A missing not-equal flag indicates that the type wasn't handled by some case.
return !someType(operandConstraint, t => getTypeFacts(t, notEqualFacts) === notEqualFacts);
}
const type = getBaseConstraintOrType(checkExpressionCached(node.expression));
if (!isLiteralType(type)) {
return false;
}
const switchTypes = getSwitchClauseTypes(node);
if (!switchTypes.length || some(switchTypes, isNeitherUnitTypeNorNever)) {
return false;
}
const mappedType = mapType(type, getRegularTypeOfLiteralType);
const result = eachTypeContainedIn(mappedType, switchTypes);
return result;
}
function functionHasImplicitReturn(func: FunctionLikeDeclaration) {