mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-29 16:29:19 -05:00
Revert "Allow (non-assert) type predicates to narrow by discriminant" (#57750)
This commit is contained in:
committed by
GitHub
parent
e5bf594753
commit
b009837298
@@ -26799,11 +26799,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
function hasMatchingArgument(expression: CallExpression | NewExpression, reference: Node) {
|
||||
if (expression.arguments) {
|
||||
for (const argument of expression.arguments) {
|
||||
if (
|
||||
isOrContainsMatchingReference(reference, argument)
|
||||
|| optionalChainContainsReference(argument, reference)
|
||||
|| getCandidateDiscriminantPropertyAccess(argument, reference)
|
||||
) {
|
||||
if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -26817,51 +26813,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getCandidateDiscriminantPropertyAccess(expr: Expression, reference: Node) {
|
||||
if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) {
|
||||
// When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in
|
||||
// getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or
|
||||
// parameter declared in the same parameter list is a candidate.
|
||||
if (isIdentifier(expr)) {
|
||||
const symbol = getResolvedSymbol(expr);
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) {
|
||||
return declaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isAccessExpression(expr)) {
|
||||
// An access expression is a candidate if the reference matches the left hand expression.
|
||||
if (isMatchingReference(reference, expr.expression)) {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
else if (isIdentifier(expr)) {
|
||||
const symbol = getResolvedSymbol(expr);
|
||||
if (isConstantVariable(symbol)) {
|
||||
const declaration = symbol.valueDeclaration!;
|
||||
// Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind'
|
||||
if (
|
||||
isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) &&
|
||||
isMatchingReference(reference, declaration.initializer.expression)
|
||||
) {
|
||||
return declaration.initializer;
|
||||
}
|
||||
// Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind'
|
||||
if (isBindingElement(declaration) && !declaration.initializer) {
|
||||
const parent = declaration.parent.parent;
|
||||
if (
|
||||
isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) &&
|
||||
isMatchingReference(reference, parent.initializer)
|
||||
) {
|
||||
return declaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getFlowNodeId(flow: FlowNode): number {
|
||||
if (!flow.id || flow.id < 0) {
|
||||
flow.id = nextFlowId;
|
||||
@@ -28232,12 +28183,57 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getCandidateDiscriminantPropertyAccess(expr: Expression) {
|
||||
if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) {
|
||||
// When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in
|
||||
// getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or
|
||||
// parameter declared in the same parameter list is a candidate.
|
||||
if (isIdentifier(expr)) {
|
||||
const symbol = getResolvedSymbol(expr);
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) {
|
||||
return declaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isAccessExpression(expr)) {
|
||||
// An access expression is a candidate if the reference matches the left hand expression.
|
||||
if (isMatchingReference(reference, expr.expression)) {
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
else if (isIdentifier(expr)) {
|
||||
const symbol = getResolvedSymbol(expr);
|
||||
if (isConstantVariable(symbol)) {
|
||||
const declaration = symbol.valueDeclaration!;
|
||||
// Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind'
|
||||
if (
|
||||
isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) &&
|
||||
isMatchingReference(reference, declaration.initializer.expression)
|
||||
) {
|
||||
return declaration.initializer;
|
||||
}
|
||||
// Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind'
|
||||
if (isBindingElement(declaration) && !declaration.initializer) {
|
||||
const parent = declaration.parent.parent;
|
||||
if (
|
||||
isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) &&
|
||||
isMatchingReference(reference, parent.initializer)
|
||||
) {
|
||||
return declaration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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, reference);
|
||||
const access = getCandidateDiscriminantPropertyAccess(expr);
|
||||
if (access) {
|
||||
const name = getAccessedPropertyName(access);
|
||||
if (name) {
|
||||
|
||||
@@ -3512,7 +3512,8 @@ export function convertJsonOption(
|
||||
convertJsonOption(opt.element, value, basePath, errors, propertyAssignment, valueExpression, sourceFile);
|
||||
}
|
||||
else if (!isString(opt.type)) {
|
||||
return convertJsonOptionOfCustomType(opt, value as string, errors, valueExpression, sourceFile);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
return convertJsonOptionOfCustomType(opt as CommandLineOptionOfCustomType, value as string, errors, valueExpression, sourceFile);
|
||||
}
|
||||
const validatedValue = validateJsonOptionValue(opt, value, errors, valueExpression, sourceFile);
|
||||
return isNullOrUndefined(validatedValue) ? validatedValue : normalizeNonListOptionValue(opt, basePath, validatedValue);
|
||||
|
||||
Reference in New Issue
Block a user