Merge pull request #26143 from mattmccutchen/issue-26130
Have getAssignmentReducedType use the comparable relation instead of typeMaybeAssignableTo.
This commit is contained in:
commit
01f6093a9c
6 changed files with 120 additions and 15 deletions
|
@ -13843,18 +13843,6 @@ namespace ts {
|
|||
return flow.id;
|
||||
}
|
||||
|
||||
function typeMaybeAssignableTo(source: Type, target: Type) {
|
||||
if (!(source.flags & TypeFlags.Union)) {
|
||||
return isTypeAssignableTo(source, target);
|
||||
}
|
||||
for (const t of (<UnionType>source).types) {
|
||||
if (isTypeAssignableTo(t, target)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove those constituent types of declaredType to which no constituent type of assignedType is assignable.
|
||||
// For example, when a variable of type number | string | boolean is assigned a value of type number | boolean,
|
||||
// we remove type string.
|
||||
|
@ -13863,7 +13851,7 @@ namespace ts {
|
|||
if (assignedType.flags & TypeFlags.Never) {
|
||||
return assignedType;
|
||||
}
|
||||
const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
|
||||
const reducedType = filterType(declaredType, t => isTypeComparableTo(assignedType, t));
|
||||
if (!(reducedType.flags & TypeFlags.Never)) {
|
||||
return reducedType;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
//// [assignmentGenericLookupTypeNarrowing.ts]
|
||||
// Repro from #26130
|
||||
|
||||
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
|
||||
declare function foo<T>(x: T): null | T;
|
||||
|
||||
function bar<K extends "foo">(key: K) {
|
||||
const element = foo(mappedObject[key]);
|
||||
if (element == null)
|
||||
return;
|
||||
const x = element.x;
|
||||
}
|
||||
|
||||
|
||||
//// [assignmentGenericLookupTypeNarrowing.js]
|
||||
// Repro from #26130
|
||||
var mappedObject = { foo: { x: "hello" } };
|
||||
function bar(key) {
|
||||
var element = foo(mappedObject[key]);
|
||||
if (element == null)
|
||||
return;
|
||||
var x = element.x;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
=== tests/cases/conformance/expressions/assignmentOperator/assignmentGenericLookupTypeNarrowing.ts ===
|
||||
// Repro from #26130
|
||||
|
||||
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
|
||||
>mappedObject : Symbol(mappedObject, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 3))
|
||||
>K : Symbol(K, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 20))
|
||||
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 41))
|
||||
>foo : Symbol(foo, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 56))
|
||||
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 62))
|
||||
|
||||
declare function foo<T>(x: T): null | T;
|
||||
>foo : Symbol(foo, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 75))
|
||||
>T : Symbol(T, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 21))
|
||||
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 24))
|
||||
>T : Symbol(T, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 21))
|
||||
>T : Symbol(T, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 21))
|
||||
|
||||
function bar<K extends "foo">(key: K) {
|
||||
>bar : Symbol(bar, Decl(assignmentGenericLookupTypeNarrowing.ts, 3, 40))
|
||||
>K : Symbol(K, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 13))
|
||||
>key : Symbol(key, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 30))
|
||||
>K : Symbol(K, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 13))
|
||||
|
||||
const element = foo(mappedObject[key]);
|
||||
>element : Symbol(element, Decl(assignmentGenericLookupTypeNarrowing.ts, 6, 7))
|
||||
>foo : Symbol(foo, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 75))
|
||||
>mappedObject : Symbol(mappedObject, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 3))
|
||||
>key : Symbol(key, Decl(assignmentGenericLookupTypeNarrowing.ts, 5, 30))
|
||||
|
||||
if (element == null)
|
||||
>element : Symbol(element, Decl(assignmentGenericLookupTypeNarrowing.ts, 6, 7))
|
||||
|
||||
return;
|
||||
const x = element.x;
|
||||
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 9, 7))
|
||||
>element.x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 41))
|
||||
>element : Symbol(element, Decl(assignmentGenericLookupTypeNarrowing.ts, 6, 7))
|
||||
>x : Symbol(x, Decl(assignmentGenericLookupTypeNarrowing.ts, 2, 41))
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
=== tests/cases/conformance/expressions/assignmentOperator/assignmentGenericLookupTypeNarrowing.ts ===
|
||||
// Repro from #26130
|
||||
|
||||
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
|
||||
>mappedObject : { foo: { x: string; }; }
|
||||
>null : null
|
||||
>x : string
|
||||
>{foo: {x: "hello"}} : { foo: { x: string; }; }
|
||||
>foo : { x: string; }
|
||||
>{x: "hello"} : { x: string; }
|
||||
>x : string
|
||||
>"hello" : "hello"
|
||||
|
||||
declare function foo<T>(x: T): null | T;
|
||||
>foo : <T>(x: T) => T
|
||||
>x : T
|
||||
>null : null
|
||||
|
||||
function bar<K extends "foo">(key: K) {
|
||||
>bar : <K extends "foo">(key: K) => void
|
||||
>key : K
|
||||
|
||||
const element = foo(mappedObject[key]);
|
||||
>element : { foo: { x: string; }; }[K]
|
||||
>foo(mappedObject[key]) : { foo: { x: string; }; }[K]
|
||||
>foo : <T>(x: T) => T
|
||||
>mappedObject[key] : { foo: { x: string; }; }[K]
|
||||
>mappedObject : { foo: { x: string; }; }
|
||||
>key : K
|
||||
|
||||
if (element == null)
|
||||
>element == null : boolean
|
||||
>element : { foo: { x: string; }; }[K]
|
||||
>null : null
|
||||
|
||||
return;
|
||||
const x = element.x;
|
||||
>x : string
|
||||
>element.x : string
|
||||
>element : { foo: { x: string; }; }[K]
|
||||
>x : string
|
||||
}
|
||||
|
|
@ -252,9 +252,9 @@ abc = merged; // missing 'd'
|
|||
>merged : Merged.E
|
||||
|
||||
merged = abc; // ok
|
||||
>merged = abc : First.E
|
||||
>merged = abc : First.E.a | First.E.b
|
||||
>merged : Merged.E
|
||||
>abc : First.E
|
||||
>abc : First.E.a | First.E.b
|
||||
|
||||
abc = merged2; // ok
|
||||
>abc = merged2 : Merged2.E
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// Repro from #26130
|
||||
|
||||
let mappedObject: {[K in "foo"]: null | {x: string}} = {foo: {x: "hello"}};
|
||||
declare function foo<T>(x: T): null | T;
|
||||
|
||||
function bar<K extends "foo">(key: K) {
|
||||
const element = foo(mappedObject[key]);
|
||||
if (element == null)
|
||||
return;
|
||||
const x = element.x;
|
||||
}
|
Loading…
Reference in a new issue