Skip to content

Commit ad62d2c

Browse files
committed
get candidate discriminant property access in hasMatchingArgument
1 parent b8b53a3 commit ad62d2c

File tree

1 file changed

+47
-47
lines changed

1 file changed

+47
-47
lines changed

src/compiler/checker.ts

Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -26743,7 +26743,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2674326743
if (
2674426744
isOrContainsMatchingReference(reference, argument)
2674526745
|| optionalChainContainsReference(argument, reference)
26746-
|| isAccessExpression(argument) && isMatchingReference(reference, argument.expression)
26746+
|| getCandidateDiscriminantPropertyAccess(argument, reference)
2674726747
) {
2674826748
return true;
2674926749
}
@@ -26758,6 +26758,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2675826758
return false;
2675926759
}
2676026760

26761+
function getCandidateDiscriminantPropertyAccess(expr: Expression, reference: Node) {
26762+
if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) {
26763+
// When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in
26764+
// getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or
26765+
// parameter declared in the same parameter list is a candidate.
26766+
if (isIdentifier(expr)) {
26767+
const symbol = getResolvedSymbol(expr);
26768+
const declaration = symbol.valueDeclaration;
26769+
if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) {
26770+
return declaration;
26771+
}
26772+
}
26773+
}
26774+
else if (isAccessExpression(expr)) {
26775+
// An access expression is a candidate if the reference matches the left hand expression.
26776+
if (isMatchingReference(reference, expr.expression)) {
26777+
return expr;
26778+
}
26779+
}
26780+
else if (isIdentifier(expr)) {
26781+
const symbol = getResolvedSymbol(expr);
26782+
if (isConstantVariable(symbol)) {
26783+
const declaration = symbol.valueDeclaration!;
26784+
// Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind'
26785+
if (
26786+
isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) &&
26787+
isMatchingReference(reference, declaration.initializer.expression)
26788+
) {
26789+
return declaration.initializer;
26790+
}
26791+
// Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind'
26792+
if (isBindingElement(declaration) && !declaration.initializer) {
26793+
const parent = declaration.parent.parent;
26794+
if (
26795+
isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) &&
26796+
isMatchingReference(reference, parent.initializer)
26797+
) {
26798+
return declaration;
26799+
}
26800+
}
26801+
}
26802+
}
26803+
return undefined;
26804+
}
26805+
2676126806
function getFlowNodeId(flow: FlowNode): number {
2676226807
if (!flow.id || flow.id < 0) {
2676326808
flow.id = nextFlowId;
@@ -28114,57 +28159,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2811428159
return result;
2811528160
}
2811628161

28117-
function getCandidateDiscriminantPropertyAccess(expr: Expression) {
28118-
if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) {
28119-
// When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in
28120-
// getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or
28121-
// parameter declared in the same parameter list is a candidate.
28122-
if (isIdentifier(expr)) {
28123-
const symbol = getResolvedSymbol(expr);
28124-
const declaration = symbol.valueDeclaration;
28125-
if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) {
28126-
return declaration;
28127-
}
28128-
}
28129-
}
28130-
else if (isAccessExpression(expr)) {
28131-
// An access expression is a candidate if the reference matches the left hand expression.
28132-
if (isMatchingReference(reference, expr.expression)) {
28133-
return expr;
28134-
}
28135-
}
28136-
else if (isIdentifier(expr)) {
28137-
const symbol = getResolvedSymbol(expr);
28138-
if (isConstantVariable(symbol)) {
28139-
const declaration = symbol.valueDeclaration!;
28140-
// Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind'
28141-
if (
28142-
isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) &&
28143-
isMatchingReference(reference, declaration.initializer.expression)
28144-
) {
28145-
return declaration.initializer;
28146-
}
28147-
// Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind'
28148-
if (isBindingElement(declaration) && !declaration.initializer) {
28149-
const parent = declaration.parent.parent;
28150-
if (
28151-
isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) &&
28152-
isMatchingReference(reference, parent.initializer)
28153-
) {
28154-
return declaration;
28155-
}
28156-
}
28157-
}
28158-
}
28159-
return undefined;
28160-
}
28161-
2816228162
function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) {
2816328163
// As long as the computed type is a subset of the declared type, we use the full declared type to detect
2816428164
// a discriminant property. In cases where the computed type isn't a subset, e.g because of a preceding type
2816528165
// predicate narrowing, we use the actual computed type.
2816628166
if (declaredType.flags & TypeFlags.Union || computedType.flags & TypeFlags.Union) {
28167-
const access = getCandidateDiscriminantPropertyAccess(expr);
28167+
const access = getCandidateDiscriminantPropertyAccess(expr, reference);
2816828168
if (access) {
2816928169
const name = getAccessedPropertyName(access);
2817028170
if (name) {

0 commit comments

Comments
 (0)