Merge pull request #26425 from mattmccutchen/issue-26405

Go back to old narrowing algorithm but don't narrow in cases like #26130
This commit is contained in:
Anders Hejlsberg 2018-08-20 15:18:29 -07:00 committed by GitHub
commit 103f894d38
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 78 additions and 6 deletions

View file

@ -13900,6 +13900,18 @@ 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.
@ -13908,8 +13920,12 @@ namespace ts {
if (assignedType.flags & TypeFlags.Never) {
return assignedType;
}
const reducedType = filterType(declaredType, t => isTypeComparableTo(assignedType, t));
if (!(reducedType.flags & TypeFlags.Never)) {
const reducedType = filterType(declaredType, t => typeMaybeAssignableTo(assignedType, t));
// Our crude heuristic produces an invalid result in some cases: see GH#26130.
// For now, when that happens, we give up and don't narrow at all. (This also
// means we'll never narrow for erroneous assignments where the assigned type
// is not assignable to the declared type.)
if (isTypeAssignableTo(assignedType, reducedType)) {
return reducedType;
}
}

View file

@ -27,6 +27,12 @@ let a: string[];
for (x of a) {
x; // string
}
// Repro from #26405
type AOrArrA<T> = T | T[];
const arr: AOrArrA<{x?: "ok"}> = [{ x: "ok" }]; // weak type
arr.push({ x: "ok" });
//// [assignmentTypeNarrowing.js]
@ -51,3 +57,5 @@ for (var _i = 0, a_1 = a; _i < a_1.length; _i++) {
x = a_1[_i];
x; // string
}
var arr = [{ x: "ok" }]; // weak type
arr.push({ x: "ok" });

View file

@ -62,3 +62,23 @@ for (x of a) {
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 0, 3))
}
// Repro from #26405
type AOrArrA<T> = T | T[];
>AOrArrA : Symbol(AOrArrA, Decl(assignmentTypeNarrowing.ts, 27, 1))
>T : Symbol(T, Decl(assignmentTypeNarrowing.ts, 31, 13))
>T : Symbol(T, Decl(assignmentTypeNarrowing.ts, 31, 13))
>T : Symbol(T, Decl(assignmentTypeNarrowing.ts, 31, 13))
const arr: AOrArrA<{x?: "ok"}> = [{ x: "ok" }]; // weak type
>arr : Symbol(arr, Decl(assignmentTypeNarrowing.ts, 32, 5))
>AOrArrA : Symbol(AOrArrA, Decl(assignmentTypeNarrowing.ts, 27, 1))
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 32, 20))
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 32, 35))
arr.push({ x: "ok" });
>arr.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>arr : Symbol(arr, Decl(assignmentTypeNarrowing.ts, 32, 5))
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assignmentTypeNarrowing.ts, 33, 10))

View file

@ -96,3 +96,25 @@ for (x of a) {
>x : string
}
// Repro from #26405
type AOrArrA<T> = T | T[];
>AOrArrA : AOrArrA<T>
const arr: AOrArrA<{x?: "ok"}> = [{ x: "ok" }]; // weak type
>arr : AOrArrA<{ x?: "ok"; }>
>x : "ok"
>[{ x: "ok" }] : { x: "ok"; }[]
>{ x: "ok" } : { x: "ok"; }
>x : "ok"
>"ok" : "ok"
arr.push({ x: "ok" });
>arr.push({ x: "ok" }) : number
>arr.push : (...items: { x?: "ok"; }[]) => number
>arr : { x?: "ok"; }[]
>push : (...items: { x?: "ok"; }[]) => number
>{ x: "ok" } : { x: "ok"; }
>x : "ok"
>"ok" : "ok"

View file

@ -252,9 +252,9 @@ abc = merged; // missing 'd'
>merged : Merged.E
merged = abc; // ok
>merged = abc : First.E.a | First.E.b
>merged = abc : First.E
>merged : Merged.E
>abc : First.E.a | First.E.b
>abc : First.E
abc = merged2; // ok
>abc = merged2 : Merged2.E

View file

@ -118,9 +118,9 @@ function f4(a: A, b: B, c: C, d: D) {
>c : C
d = d;
>d = d : 1 | 2
>d = d : D
>d : D
>d : D
>d : 1 | 2
}
function f5(a: A, b: B, c: C, d: D) {

View file

@ -26,3 +26,9 @@ let a: string[];
for (x of a) {
x; // string
}
// Repro from #26405
type AOrArrA<T> = T | T[];
const arr: AOrArrA<{x?: "ok"}> = [{ x: "ok" }]; // weak type
arr.push({ x: "ok" });