Skip to content

Commit 30b06c7

Browse files
committed
Redo older fix causing new bug by extending getDeclaredOrApparentType instead of getTypeWithFacts
1 parent 31a1a4a commit 30b06c7

File tree

3 files changed

+14
-22
lines changed

3 files changed

+14
-22
lines changed

src/compiler/checker.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4308,7 +4308,8 @@ namespace ts {
43084308
if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) {
43094309
parentType = getNonNullableType(parentType);
43104310
}
4311-
const declaredType = getTypeOfPropertyOfType(parentType, text);
4311+
const propType = getTypeOfPropertyOfType(parentType, text);
4312+
const declaredType = propType && getDeclaredOrApparentType(propType, declaration.name);
43124313
type = declaredType && getFlowTypeOfReference(declaration, declaredType) ||
43134314
isNumericLiteralName(text) && getIndexTypeOfType(parentType, IndexKind.Number) ||
43144315
getIndexTypeOfType(parentType, IndexKind.String);
@@ -12039,16 +12040,6 @@ namespace ts {
1203912040
}
1204012041

1204112042
function getTypeWithFacts(type: Type, include: TypeFacts) {
12042-
if (type.flags & TypeFlags.IndexedAccess) {
12043-
// TODO (weswig): This is a substitute for a lazy negated type to remove the types indicated by the TypeFacts from the (potential) union the IndexedAccess refers to
12044-
// - See discussion in https://github.com/Microsoft/TypeScript/pull/19275 for details, and test `strictNullNotNullIndexTypeShouldWork` for current behavior
12045-
const baseConstraint = getBaseConstraintOfType(type) || emptyObjectType;
12046-
const result = filterType(baseConstraint, t => (getTypeFacts(t) & include) !== 0);
12047-
if (result !== baseConstraint) {
12048-
return result;
12049-
}
12050-
return type;
12051-
}
1205212043
return filterType(type, t => (getTypeFacts(t) & include) !== 0);
1205312044
}
1205412045

@@ -13162,19 +13153,20 @@ namespace ts {
1316213153
const parent = node.parent;
1316313154
return parent.kind === SyntaxKind.PropertyAccessExpression ||
1316413155
parent.kind === SyntaxKind.CallExpression && (<CallExpression>parent).expression === node ||
13165-
parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>parent).expression === node;
13156+
parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>parent).expression === node ||
13157+
parent.kind === SyntaxKind.NonNullExpression ||
13158+
parent.kind === SyntaxKind.BindingElement && (<BindingElement>parent).name === node && !!(<BindingElement>parent).initializer;
1316613159
}
1316713160

1316813161
function typeHasNullableConstraint(type: Type) {
1316913162
return type.flags & TypeFlags.TypeVariable && maybeTypeOfKind(getBaseConstraintOfType(type) || emptyObjectType, TypeFlags.Nullable);
1317013163
}
1317113164

13172-
function getDeclaredOrApparentType(symbol: Symbol, node: Node) {
13165+
function getDeclaredOrApparentType(type: Type, node: Node) {
1317313166
// When a node is the left hand expression of a property access, element access, or call expression,
1317413167
// and the type of the node includes type variables with constraints that are nullable, we fetch the
1317513168
// apparent type of the node *before* performing control flow analysis such that narrowings apply to
1317613169
// the constraint type.
13177-
const type = getTypeOfSymbol(symbol);
1317813170
if (isApparentTypePosition(node) && forEachType(type, typeHasNullableConstraint)) {
1317913171
return mapType(getWidenedType(type), getApparentType);
1318013172
}
@@ -13264,7 +13256,7 @@ namespace ts {
1326413256
checkCollisionWithCapturedNewTargetVariable(node, node);
1326513257
checkNestedBlockScopedBinding(node, symbol);
1326613258

13267-
const type = getDeclaredOrApparentType(localOrExportSymbol, node);
13259+
const type = getDeclaredOrApparentType(getTypeOfSymbol(localOrExportSymbol), node);
1326813260
const assignmentKind = getAssignmentTargetKind(node);
1326913261

1327013262
if (assignmentKind) {
@@ -13338,7 +13330,7 @@ namespace ts {
1333813330
return convertAutoToAny(flowType);
1333913331
}
1334013332
}
13341-
else if (!assumeInitialized && !(getFalsyFlags(getApparentType(type)) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
13333+
else if (!assumeInitialized && !(getFalsyFlags(type) & TypeFlags.Undefined) && getFalsyFlags(flowType) & TypeFlags.Undefined) {
1334213334
error(node, Diagnostics.Variable_0_is_used_before_being_assigned, symbolToString(symbol));
1334313335
// Return the declared type to reduce follow-on errors
1334413336
return type;
@@ -15816,7 +15808,7 @@ namespace ts {
1581615808
return unknownType;
1581715809
}
1581815810
}
15819-
propType = getDeclaredOrApparentType(prop, node);
15811+
propType = getDeclaredOrApparentType(getTypeOfSymbol(prop), node);
1582015812
}
1582115813
// Only compute control flow type if this is a property access expression that isn't an
1582215814
// assignment target, and the referenced property was declared as a variable, property,

tests/baselines/reference/definiteAssignmentOfDestructuredVariable.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ class C<T extends Options> {
4040
>b : T["b"]
4141

4242
a;
43-
>a : number | object | undefined
43+
>a : T["a"]
4444
}
4545
}

tests/baselines/reference/strictNullNotNullIndexTypeShouldWork.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ class Test<T extends A> {
2323
this.attrs.params!.name;
2424
>this.attrs.params!.name : string
2525
>this.attrs.params! : { name: string; }
26-
>this.attrs.params : T["params"]
26+
>this.attrs.params : { name: string; } | undefined
2727
>this.attrs : Readonly<T>
2828
>this : this
2929
>attrs : Readonly<T>
30-
>params : T["params"]
30+
>params : { name: string; } | undefined
3131
>name : string
3232
}
3333
}
@@ -80,10 +80,10 @@ class Test2<T extends A> {
8080

8181
return this.attrs.params!; // Return type should maintain relationship with `T` after being not-null-asserted, ideally
8282
>this.attrs.params! : { name: string; }
83-
>this.attrs.params : T["params"]
83+
>this.attrs.params : { name: string; } | undefined
8484
>this.attrs : Readonly<T>
8585
>this : this
8686
>attrs : Readonly<T>
87-
>params : T["params"]
87+
>params : { name: string; } | undefined
8888
}
8989
}

0 commit comments

Comments
 (0)