Skip to content

Commit 01f6093

Browse files
authored
Merge pull request #26143 from mattmccutchen/issue-26130
Have getAssignmentReducedType use the comparable relation instead of typeMaybeAssignableTo.
2 parents 20ebe1e + d45e422 commit 01f6093

File tree

6 files changed

+120
-15
lines changed

6 files changed

+120
-15
lines changed

src/compiler/checker.ts

+1-13
Original file line numberDiff line numberDiff line change
@@ -13843,18 +13843,6 @@ namespace ts {
1384313843
return flow.id;
1384413844
}
1384513845

13846-
function typeMaybeAssignableTo(source: Type, target: Type) {
13847-
if (!(source.flags & TypeFlags.Union)) {
13848-
return isTypeAssignableTo(source, target);
13849-
}
13850-
for (const t of (<UnionType>source).types) {
13851-
if (isTypeAssignableTo(t, target)) {
13852-
return true;
13853-
}
13854-
}
13855-
return false;
13856-
}
13857-
1385813846
// Remove those constituent types of declaredType to which no constituent type of assignedType is assignable.
1385913847
// For example, when a variable of type number | string | boolean is assigned a value of type number | boolean,
1386013848
// we remove type string.
@@ -13863,7 +13851,7 @@ namespace ts {
1386313851
if (assignedType.flags & TypeFlags.Never) {
1386413852
return assignedType;
1386513853
}
13866-
const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
13854+
const reducedType = filterType(declaredType, t => isTypeComparableTo(assignedType, t));
1386713855
if (!(reducedType.flags & TypeFlags.Never)) {
1386813856
return reducedType;
1386913857
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [assignmentGenericLookupTypeNarrowing.ts]
2+
// Repro from #26130
3+
4+
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
5+
declare function foo<T>(x: T): null | T;
6+
7+
function bar<K extends "foo">(key: K) {
8+
const element = foo(mappedObject[key]);
9+
if (element == null)
10+
return;
11+
const x = element.x;
12+
}
13+
14+
15+
//// [assignmentGenericLookupTypeNarrowing.js]
16+
// Repro from #26130
17+
var mappedObject = { foo: { x: "hello" } };
18+
function bar(key) {
19+
var element = foo(mappedObject[key]);
20+
if (element == null)
21+
return;
22+
var x = element.x;
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
=== tests/cases/conformance/expressions/assignmentOperator/assignmentGenericLookupTypeNarrowing.ts ===
2+
// Repro from #26130
3+
4+
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
5+
>mappedObject : Symbol(mappedObject, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 3))
6+
>K : Symbol(K, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 20))
7+
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 41))
8+
>foo : Symbol(foo, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 56))
9+
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 62))
10+
11+
declare function foo<T>(x: T): null | T;
12+
>foo : Symbol(foo, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 75))
13+
>T : Symbol(T, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 21))
14+
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 24))
15+
>T : Symbol(T, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 21))
16+
>T : Symbol(T, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 21))
17+
18+
function bar<K extends "foo">(key: K) {
19+
>bar : Symbol(bar, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 40))
20+
>K : Symbol(K, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 13))
21+
>key : Symbol(key, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 30))
22+
>K : Symbol(K, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 13))
23+
24+
const element = foo(mappedObject[key]);
25+
>element : Symbol(element, Decl(assignmentGenericLookupTypeNarrowing.ts, 6, 7))
26+
>foo : Symbol(foo, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 75))
27+
>mappedObject : Symbol(mappedObject, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 3))
28+
>key : Symbol(key, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 30))
29+
30+
if (element == null)
31+
>element : Symbol(element, Decl(assignmentGenericLookupTypeNarrowing.ts, 6, 7))
32+
33+
return;
34+
const x = element.x;
35+
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 9, 7))
36+
>element.x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 41))
37+
>element : Symbol(element, Decl(assignmentGenericLookupTypeNarrowing.ts, 6, 7))
38+
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 41))
39+
}
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
=== tests/cases/conformance/expressions/assignmentOperator/assignmentGenericLookupTypeNarrowing.ts ===
2+
// Repro from #26130
3+
4+
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
5+
>mappedObject : { foo: { x: string; }; }
6+
>null : null
7+
>x : string
8+
>{foo: {x: "hello"}} : { foo: { x: string; }; }
9+
>foo : { x: string; }
10+
>{x: "hello"} : { x: string; }
11+
>x : string
12+
>"hello" : "hello"
13+
14+
declare function foo<T>(x: T): null | T;
15+
>foo : <T>(x: T) => T
16+
>x : T
17+
>null : null
18+
19+
function bar<K extends "foo">(key: K) {
20+
>bar : <K extends "foo">(key: K) => void
21+
>key : K
22+
23+
const element = foo(mappedObject[key]);
24+
>element : { foo: { x: string; }; }[K]
25+
>foo(mappedObject[key]) : { foo: { x: string; }; }[K]
26+
>foo : <T>(x: T) => T
27+
>mappedObject[key] : { foo: { x: string; }; }[K]
28+
>mappedObject : { foo: { x: string; }; }
29+
>key : K
30+
31+
if (element == null)
32+
>element == null : boolean
33+
>element : { foo: { x: string; }; }[K]
34+
>null : null
35+
36+
return;
37+
const x = element.x;
38+
>x : string
39+
>element.x : string
40+
>element : { foo: { x: string; }; }[K]
41+
>x : string
42+
}
43+

tests/baselines/reference/enumAssignmentCompat3.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ abc = merged; // missing 'd'
252252
>merged : Merged.E
253253

254254
merged = abc; // ok
255-
>merged = abc : First.E
255+
>merged = abc : First.E.a | First.E.b
256256
>merged : Merged.E
257-
>abc : First.E
257+
>abc : First.E.a | First.E.b
258258

259259
abc = merged2; // ok
260260
>abc = merged2 : Merged2.E
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Repro from #26130
2+
3+
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
4+
declare function foo<T>(x: T): null | T;
5+
6+
function bar<K extends "foo">(key: K) {
7+
const element = foo(mappedObject[key]);
8+
if (element == null)
9+
return;
10+
const x = element.x;
11+
}

0 commit comments

Comments
 (0)