Skip to content

Commit daf8937

Browse files
committed
Merge branch 'generic-cfa-more-fixes' into generic-cfa
2 parents 9f6b6d3 + 795d244 commit daf8937

7 files changed

+142
-21
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24026,16 +24026,7 @@ namespace ts {
2402624026

2402724027
function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean, isRelated: (source: Type, target: Type) => boolean) {
2402824028
if (!assumeTrue) {
24029-
return filterType(type, t => {
24030-
if (!isRelated(t, candidate)) {
24031-
return true;
24032-
}
24033-
const constraint = getBaseConstraintOfType(t);
24034-
if (constraint && constraint !== t) {
24035-
return !isRelated(constraint, candidate);
24036-
}
24037-
return false;
24038-
});
24029+
return filterType(type, t => !isRelated(t, candidate));
2403924030
}
2404024031
// If the current type is a union type, remove all constituents that couldn't be instances of
2404124032
// the candidate type. If one or more constituents remain, return a union of those.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [genericCapturingFunctionNarrowing.ts]
2+
function needsToNarrowTheType<First extends { foo: string }, Second extends { bar: string }, SubFirst extends First, SubFirstMore extends First & {other: string}>(thing: First | SubFirst | SubFirstMore | Second) {
3+
if (hasAFoo(thing)) {
4+
console.log(thing.foo);
5+
}
6+
else {
7+
// I would expect this to work because the type should be narrowed in this branch to `Second`
8+
console.log(thing.bar); // Error: Property 'bar' does not exist on type 'First | Second'.
9+
}
10+
11+
function hasAFoo(value: First | Second): value is First {
12+
return "foo" in value;
13+
}
14+
}
15+
16+
//// [genericCapturingFunctionNarrowing.js]
17+
function needsToNarrowTheType(thing) {
18+
if (hasAFoo(thing)) {
19+
console.log(thing.foo);
20+
}
21+
else {
22+
// I would expect this to work because the type should be narrowed in this branch to `Second`
23+
console.log(thing.bar); // Error: Property 'bar' does not exist on type 'First | Second'.
24+
}
25+
function hasAFoo(value) {
26+
return "foo" in value;
27+
}
28+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
=== tests/cases/compiler/genericCapturingFunctionNarrowing.ts ===
2+
function needsToNarrowTheType<First extends { foo: string }, Second extends { bar: string }, SubFirst extends First, SubFirstMore extends First & {other: string}>(thing: First | SubFirst | SubFirstMore | Second) {
3+
>needsToNarrowTheType : Symbol(needsToNarrowTheType, Decl(genericCapturingFunctionNarrowing.ts, 0, 0))
4+
>First : Symbol(First, Decl(genericCapturingFunctionNarrowing.ts, 0, 30))
5+
>foo : Symbol(foo, Decl(genericCapturingFunctionNarrowing.ts, 0, 45))
6+
>Second : Symbol(Second, Decl(genericCapturingFunctionNarrowing.ts, 0, 60))
7+
>bar : Symbol(bar, Decl(genericCapturingFunctionNarrowing.ts, 0, 77))
8+
>SubFirst : Symbol(SubFirst, Decl(genericCapturingFunctionNarrowing.ts, 0, 92))
9+
>First : Symbol(First, Decl(genericCapturingFunctionNarrowing.ts, 0, 30))
10+
>SubFirstMore : Symbol(SubFirstMore, Decl(genericCapturingFunctionNarrowing.ts, 0, 116))
11+
>First : Symbol(First, Decl(genericCapturingFunctionNarrowing.ts, 0, 30))
12+
>other : Symbol(other, Decl(genericCapturingFunctionNarrowing.ts, 0, 147))
13+
>thing : Symbol(thing, Decl(genericCapturingFunctionNarrowing.ts, 0, 163))
14+
>First : Symbol(First, Decl(genericCapturingFunctionNarrowing.ts, 0, 30))
15+
>SubFirst : Symbol(SubFirst, Decl(genericCapturingFunctionNarrowing.ts, 0, 92))
16+
>SubFirstMore : Symbol(SubFirstMore, Decl(genericCapturingFunctionNarrowing.ts, 0, 116))
17+
>Second : Symbol(Second, Decl(genericCapturingFunctionNarrowing.ts, 0, 60))
18+
19+
if (hasAFoo(thing)) {
20+
>hasAFoo : Symbol(hasAFoo, Decl(genericCapturingFunctionNarrowing.ts, 7, 5))
21+
>thing : Symbol(thing, Decl(genericCapturingFunctionNarrowing.ts, 0, 163))
22+
23+
console.log(thing.foo);
24+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
25+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
26+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
27+
>thing.foo : Symbol(foo, Decl(genericCapturingFunctionNarrowing.ts, 0, 45))
28+
>thing : Symbol(thing, Decl(genericCapturingFunctionNarrowing.ts, 0, 163))
29+
>foo : Symbol(foo, Decl(genericCapturingFunctionNarrowing.ts, 0, 45))
30+
}
31+
else {
32+
// I would expect this to work because the type should be narrowed in this branch to `Second`
33+
console.log(thing.bar); // Error: Property 'bar' does not exist on type 'First | Second'.
34+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
35+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
36+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
37+
>thing.bar : Symbol(bar, Decl(genericCapturingFunctionNarrowing.ts, 0, 77))
38+
>thing : Symbol(thing, Decl(genericCapturingFunctionNarrowing.ts, 0, 163))
39+
>bar : Symbol(bar, Decl(genericCapturingFunctionNarrowing.ts, 0, 77))
40+
}
41+
42+
function hasAFoo(value: First | Second): value is First {
43+
>hasAFoo : Symbol(hasAFoo, Decl(genericCapturingFunctionNarrowing.ts, 7, 5))
44+
>value : Symbol(value, Decl(genericCapturingFunctionNarrowing.ts, 9, 21))
45+
>First : Symbol(First, Decl(genericCapturingFunctionNarrowing.ts, 0, 30))
46+
>Second : Symbol(Second, Decl(genericCapturingFunctionNarrowing.ts, 0, 60))
47+
>value : Symbol(value, Decl(genericCapturingFunctionNarrowing.ts, 9, 21))
48+
>First : Symbol(First, Decl(genericCapturingFunctionNarrowing.ts, 0, 30))
49+
50+
return "foo" in value;
51+
>value : Symbol(value, Decl(genericCapturingFunctionNarrowing.ts, 9, 21))
52+
}
53+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
=== tests/cases/compiler/genericCapturingFunctionNarrowing.ts ===
2+
function needsToNarrowTheType<First extends { foo: string }, Second extends { bar: string }, SubFirst extends First, SubFirstMore extends First & {other: string}>(thing: First | SubFirst | SubFirstMore | Second) {
3+
>needsToNarrowTheType : <First extends { foo: string; }, Second extends { bar: string; }, SubFirst extends First, SubFirstMore extends First & { other: string; }>(thing: First | SubFirst | SubFirstMore | Second) => void
4+
>foo : string
5+
>bar : string
6+
>other : string
7+
>thing : First | Second | SubFirst | SubFirstMore
8+
9+
if (hasAFoo(thing)) {
10+
>hasAFoo(thing) : boolean
11+
>hasAFoo : (value: First | Second) => value is First
12+
>thing : First | Second | SubFirst | SubFirstMore
13+
14+
console.log(thing.foo);
15+
>console.log(thing.foo) : void
16+
>console.log : (...data: any[]) => void
17+
>console : Console
18+
>log : (...data: any[]) => void
19+
>thing.foo : string
20+
>thing : First | SubFirst | SubFirstMore
21+
>foo : string
22+
}
23+
else {
24+
// I would expect this to work because the type should be narrowed in this branch to `Second`
25+
console.log(thing.bar); // Error: Property 'bar' does not exist on type 'First | Second'.
26+
>console.log(thing.bar) : void
27+
>console.log : (...data: any[]) => void
28+
>console : Console
29+
>log : (...data: any[]) => void
30+
>thing.bar : string
31+
>thing : Second
32+
>bar : string
33+
}
34+
35+
function hasAFoo(value: First | Second): value is First {
36+
>hasAFoo : (value: First | Second) => value is First
37+
>value : First | Second
38+
39+
return "foo" in value;
40+
>"foo" in value : boolean
41+
>"foo" : "foo"
42+
>value : First | Second
43+
}
44+
}

tests/baselines/reference/quickinfoTypeAtReturnPositionsInaccurate.errors.txt

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
tests/cases/compiler/quickinfoTypeAtReturnPositionsInaccurate.ts(33,15): error TS2339: Property 'numExclusive' does not exist on type 'NumClass<number> | StrClass<string>'.
22
Property 'numExclusive' does not exist on type 'StrClass<string>'.
3-
tests/cases/compiler/quickinfoTypeAtReturnPositionsInaccurate.ts(101,11): error TS2322: Type 'Program | T' is not assignable to type 'Program'.
4-
Type 'T' is not assignable to type 'Program'.
5-
Property 'state' is missing in type 'BuilderProgram' but required in type 'Program'.
63

74

8-
==== tests/cases/compiler/quickinfoTypeAtReturnPositionsInaccurate.ts (2 errors) ====
5+
==== tests/cases/compiler/quickinfoTypeAtReturnPositionsInaccurate.ts (1 errors) ====
96
class NumClass<T extends number> {
107
private value!: T;
118
public get(): T {
@@ -110,9 +107,4 @@ tests/cases/compiler/quickinfoTypeAtReturnPositionsInaccurate.ts(101,11): error
110107
declare function isBuilderProgram<T extends BuilderProgram>(program: Program | T): program is T;
111108
export function listFiles<T extends BuilderProgram>(program: Program | T) {
112109
const x: Program = isBuilderProgram(program) ? program.getProgram() : program;
113-
~
114-
!!! error TS2322: Type 'Program | T' is not assignable to type 'Program'.
115-
!!! error TS2322: Type 'T' is not assignable to type 'Program'.
116-
!!! error TS2322: Property 'state' is missing in type 'BuilderProgram' but required in type 'Program'.
117-
!!! related TS2728 tests/cases/compiler/quickinfoTypeAtReturnPositionsInaccurate.ts:97:5: 'state' is declared here.
118110
}

tests/baselines/reference/quickinfoTypeAtReturnPositionsInaccurate.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,13 @@ export function listFiles<T extends BuilderProgram>(program: Program | T) {
226226

227227
const x: Program = isBuilderProgram(program) ? program.getProgram() : program;
228228
>x : Program
229-
>isBuilderProgram(program) ? program.getProgram() : program : Program | T
229+
>isBuilderProgram(program) ? program.getProgram() : program : Program
230230
>isBuilderProgram(program) : boolean
231231
>isBuilderProgram : <T extends BuilderProgram>(program: Program | T) => program is T
232232
>program : Program | T
233233
>program.getProgram() : Program
234234
>program.getProgram : () => Program
235235
>program : T
236236
>getProgram : () => Program
237-
>program : Program | T
237+
>program : Program
238238
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
function needsToNarrowTheType<First extends { foo: string }, Second extends { bar: string }, SubFirst extends First, SubFirstMore extends First & {other: string}>(thing: First | SubFirst | SubFirstMore | Second) {
2+
if (hasAFoo(thing)) {
3+
console.log(thing.foo);
4+
}
5+
else {
6+
// I would expect this to work because the type should be narrowed in this branch to `Second`
7+
console.log(thing.bar); // Error: Property 'bar' does not exist on type 'First | Second'.
8+
}
9+
10+
function hasAFoo(value: First | Second): value is First {
11+
return "foo" in value;
12+
}
13+
}

0 commit comments

Comments
 (0)