Skip to content

Commit a4507c9

Browse files
authored
Favor asserted type in type predicate narrowing (#50044)
* Favor asserted type in type predicate narrowing * Accept new baselines
1 parent ebd42ab commit a4507c9

7 files changed

+20
-16
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25428,8 +25428,12 @@ namespace ts {
2542825428
const discriminant = keyPropertyName && getTypeOfPropertyOfType(c, keyPropertyName);
2542925429
const matching = discriminant && getConstituentTypeForKeyType(type as UnionType, discriminant);
2543025430
// For each constituent t in the current type, if t and and c are directly related, pick the most
25431-
// specific of the two.
25432-
const directlyRelated = mapType(matching || type, t => isRelated(t, c) ? t : isRelated(c, t) ? c : neverType);
25431+
// specific of the two. When t and c are related in both directions, we prefer c for type predicates
25432+
// because that is the asserted type, but t for `instanceof` because generics aren't reflected in
25433+
// prototype object types.
25434+
const directlyRelated = mapType(matching || type, checkDerived ?
25435+
t => isTypeDerivedFrom(t, c) ? t : isTypeDerivedFrom(c, t) ? c : neverType :
25436+
t => isTypeSubtypeOf(c, t) ? c : isTypeSubtypeOf(t, c) ? t : neverType);
2543325437
// If no constituents are directly related, create intersections for any generic constituents that
2543425438
// are related by constraint.
2543525439
return directlyRelated.flags & TypeFlags.Never ?

tests/baselines/reference/controlFlowBinaryOrExpression.symbols

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,19 @@ if (isNodeList(sourceObj)) {
6464
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
6565

6666
sourceObj.length;
67-
>sourceObj.length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
67+
>sourceObj.length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27))
6868
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
69-
>length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
69+
>length : Symbol(NodeList.length, Decl(controlFlowBinaryOrExpression.ts, 10, 27))
7070
}
7171

7272
if (isHTMLCollection(sourceObj)) {
7373
>isHTMLCollection : Symbol(isHTMLCollection, Decl(controlFlowBinaryOrExpression.ts, 18, 67))
7474
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
7575

7676
sourceObj.length;
77-
>sourceObj.length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
77+
>sourceObj.length : Symbol(HTMLCollection.length, Decl(controlFlowBinaryOrExpression.ts, 14, 33))
7878
>sourceObj : Symbol(sourceObj, Decl(controlFlowBinaryOrExpression.ts, 23, 3))
79-
>length : Symbol(length, Decl(controlFlowBinaryOrExpression.ts, 10, 27), Decl(controlFlowBinaryOrExpression.ts, 14, 33))
79+
>length : Symbol(HTMLCollection.length, Decl(controlFlowBinaryOrExpression.ts, 14, 33))
8080
}
8181

8282
if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {

tests/baselines/reference/controlFlowBinaryOrExpression.types

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,26 +69,26 @@ if (isNodeList(sourceObj)) {
6969

7070
sourceObj.length;
7171
>sourceObj.length : number
72-
>sourceObj : NodeList | HTMLCollection
72+
>sourceObj : NodeList
7373
>length : number
7474
}
7575

7676
if (isHTMLCollection(sourceObj)) {
7777
>isHTMLCollection(sourceObj) : boolean
7878
>isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection
79-
>sourceObj : EventTargetLike
79+
>sourceObj : NodeList | { a: string; }
8080

8181
sourceObj.length;
8282
>sourceObj.length : number
83-
>sourceObj : NodeList | HTMLCollection
83+
>sourceObj : HTMLCollection
8484
>length : number
8585
}
8686

8787
if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) {
8888
>isNodeList(sourceObj) || isHTMLCollection(sourceObj) : boolean
8989
>isNodeList(sourceObj) : boolean
9090
>isNodeList : (sourceObj: any) => sourceObj is NodeList
91-
>sourceObj : EventTargetLike
91+
>sourceObj : HTMLCollection | { a: string; }
9292
>isHTMLCollection(sourceObj) : boolean
9393
>isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection
9494
>sourceObj : { a: string; }

tests/baselines/reference/instanceofWithStructurallyIdenticalTypes.symbols

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,9 @@ function foo2(x: C1 | C2 | C3): string {
9595
>x : Symbol(x, Decl(instanceofWithStructurallyIdenticalTypes.ts, 23, 14))
9696

9797
return x.item;
98-
>x.item : Symbol(item, Decl(instanceofWithStructurallyIdenticalTypes.ts, 2, 10), Decl(instanceofWithStructurallyIdenticalTypes.ts, 4, 10))
98+
>x.item : Symbol(C1.item, Decl(instanceofWithStructurallyIdenticalTypes.ts, 2, 10))
9999
>x : Symbol(x, Decl(instanceofWithStructurallyIdenticalTypes.ts, 23, 14))
100-
>item : Symbol(item, Decl(instanceofWithStructurallyIdenticalTypes.ts, 2, 10), Decl(instanceofWithStructurallyIdenticalTypes.ts, 4, 10))
100+
>item : Symbol(C1.item, Decl(instanceofWithStructurallyIdenticalTypes.ts, 2, 10))
101101
}
102102
else if (isC2(x)) {
103103
>isC2 : Symbol(isC2, Decl(instanceofWithStructurallyIdenticalTypes.ts, 19, 66))

tests/baselines/reference/instanceofWithStructurallyIdenticalTypes.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ function foo2(x: C1 | C2 | C3): string {
8585

8686
return x.item;
8787
>x.item : string
88-
>x : C1 | C3
88+
>x : C1
8989
>item : string
9090
}
9191
else if (isC2(x)) {

tests/baselines/reference/typePredicateStructuralMatch.symbols

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ function getResults1(value: Results | { data: Results }): Results {
5151
return isResponseInData(value) ? value.data : value;
5252
>isResponseInData : Symbol(isResponseInData, Decl(typePredicateStructuralMatch.ts, 9, 24))
5353
>value : Symbol(value, Decl(typePredicateStructuralMatch.ts, 15, 21))
54-
>value.data : Symbol(data, Decl(typePredicateStructuralMatch.ts, 15, 39))
54+
>value.data : Symbol(data, Decl(typePredicateStructuralMatch.ts, 11, 63))
5555
>value : Symbol(value, Decl(typePredicateStructuralMatch.ts, 15, 21))
56-
>data : Symbol(data, Decl(typePredicateStructuralMatch.ts, 15, 39))
56+
>data : Symbol(data, Decl(typePredicateStructuralMatch.ts, 11, 63))
5757
>value : Symbol(value, Decl(typePredicateStructuralMatch.ts, 15, 21))
5858
}
5959

tests/baselines/reference/unionWithIndexSignature.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export function flatten<T extends number|TypedArray>(arr: T) {
5555

5656
arr[1];
5757
>arr[1] : number
58-
>arr : TypedArray
58+
>arr : Int32Array | Uint8Array
5959
>1 : 1
6060
}
6161
}

0 commit comments

Comments
 (0)