Skip to content

Commit 7cba33c

Browse files
committed
In obj[key], omit non-nullable check when obj and key are both generic
1 parent 0c33c13 commit 7cba33c

File tree

1 file changed

+9
-17
lines changed

1 file changed

+9
-17
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29665,15 +29665,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2966529665

2966629666
function isConstraintPosition(type: Type, node: Node) {
2966729667
const parent = node.parent;
29668-
// In an element access obj[x], we consider obj to be in a constraint position, except when obj is of
29669-
// a generic type without a nullable constraint and x is a generic type. This is because when both obj
29670-
// and x are of generic types T and K, we want the resulting type to be T[K].
29668+
// In an element access obj[key], we consider obj to be in a constraint position, except when
29669+
// obj and key both have generic types. When obj and key are of generic types T and K, we want
29670+
// the resulting type to be T[K].
2967129671
return parent.kind === SyntaxKind.PropertyAccessExpression ||
2967229672
parent.kind === SyntaxKind.QualifiedName ||
2967329673
parent.kind === SyntaxKind.CallExpression && (parent as CallExpression).expression === node ||
2967429674
parent.kind === SyntaxKind.NewExpression && (parent as NewExpression).expression === node ||
2967529675
parent.kind === SyntaxKind.ElementAccessExpression && (parent as ElementAccessExpression).expression === node &&
29676-
!(someType(type, isGenericTypeWithoutNullableConstraint) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression)));
29676+
!(isGenericObjectType(type) && isGenericIndexType(getTypeOfExpression((parent as ElementAccessExpression).argumentExpression)));
2967729677
}
2967829678

2967929679
function isGenericTypeWithUnionConstraint(type: Type): boolean {
@@ -29682,12 +29682,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2968229682
!!(type.flags & TypeFlags.Instantiable && getBaseConstraintOrType(type).flags & (TypeFlags.Nullable | TypeFlags.Union));
2968329683
}
2968429684

29685-
function isGenericTypeWithoutNullableConstraint(type: Type): boolean {
29686-
return type.flags & TypeFlags.Intersection ?
29687-
some((type as IntersectionType).types, isGenericTypeWithoutNullableConstraint) :
29688-
!!(type.flags & TypeFlags.Instantiable && !maybeTypeOfKind(getBaseConstraintOrType(type), TypeFlags.Nullable));
29689-
}
29690-
2969129685
function hasContextualTypeWithNoGenericTypes(node: Node, checkMode: CheckMode | undefined) {
2969229686
// Computing the contextual type for a child of a JSX element involves resolving the type of the
2969329687
// element's tag name, so we exclude that here to avoid circularities.
@@ -34589,14 +34583,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3458934583
}
3459034584

3459134585
function checkIndexedAccess(node: ElementAccessExpression, checkMode: CheckMode | undefined): Type {
34592-
return node.flags & NodeFlags.OptionalChain ? checkElementAccessChain(node as ElementAccessChain, checkMode) :
34593-
checkElementAccessExpression(node, checkNonNullExpression(node.expression), checkMode);
34594-
}
34595-
34596-
function checkElementAccessChain(node: ElementAccessChain, checkMode: CheckMode | undefined) {
34586+
const isOptional = node.flags & NodeFlags.OptionalChain;
3459734587
const exprType = checkExpression(node.expression);
34598-
const nonOptionalType = getOptionalExpressionType(exprType, node.expression);
34599-
return propagateOptionalTypeMarker(checkElementAccessExpression(node, checkNonNullType(nonOptionalType, node.expression), checkMode), node, nonOptionalType !== exprType);
34588+
const nonOptionalType = isOptional ? getOptionalExpressionType(exprType, node.expression) : exprType;
34589+
const nonNullType = maybeTypeOfKind(nonOptionalType, TypeFlags.Unknown | TypeFlags.Nullable) ? checkNonNullType(nonOptionalType, node.expression) : nonOptionalType;
34590+
const elementType = checkElementAccessExpression(node, nonNullType, checkMode);
34591+
return isOptional ? propagateOptionalTypeMarker(elementType, node as ElementAccessChain, nonOptionalType !== exprType) : elementType;
3460034592
}
3460134593

3460234594
function checkElementAccessExpression(node: ElementAccessExpression, exprType: Type, checkMode: CheckMode | undefined): Type {

0 commit comments

Comments
 (0)