-
Notifications
You must be signed in to change notification settings - Fork 12.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Track source and target relationship stack depth seperately, only inc…
…rease on change in value (#41821) * Track source and target relationship stack depth seperately, only increase on change in value * Add baselines for test from #43485 * Bail on unwrapping conditional constraints on the source side when the source conditional is already known to be spooling out of control * More usage of isDeeplyNestedType to block _specifically_ conditional recursion on only one side * Negative cases of getNarrowedType that match the exact type should be filtered out, even when generic * Add test and fix for #44404 * Swap to manually specifying left and right recursion * Rename Left -> Source, Right -> Target Co-authored-by: Andrew Branch <andrew@wheream.io>
- Loading branch information
1 parent
96f259d
commit 612c92d
Showing
25 changed files
with
1,368 additions
and
133 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
196 changes: 196 additions & 0 deletions
196
...rcularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt
Large diffs are not rendered by default.
Oops, something went wrong.
20 changes: 20 additions & 0 deletions
20
tests/baselines/reference/conditionalTypeVarianceBigArrayConstraintsPerformance.errors.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
tests/cases/compiler/conditionalTypeVarianceBigArrayConstraintsPerformance.ts(9,5): error TS2322: Type 'Stuff<U>' is not assignable to type 'Stuff<T>'. | ||
Type 'U' is not assignable to type 'T'. | ||
'T' could be instantiated with an arbitrary type which could be unrelated to 'U'. | ||
|
||
|
||
==== tests/cases/compiler/conditionalTypeVarianceBigArrayConstraintsPerformance.ts (1 errors) ==== | ||
/// <reference path="/.lib/react16.d.ts" /> | ||
|
||
type Stuff<T> = | ||
T extends keyof JSX.IntrinsicElements | ||
? JSX.IntrinsicElements[T] | ||
: any; | ||
|
||
function F<T, U>(p1: Stuff<T>, p2: Stuff<U>) { | ||
p1 = p2; // Error | ||
~~ | ||
!!! error TS2322: Type 'Stuff<U>' is not assignable to type 'Stuff<T>'. | ||
!!! error TS2322: Type 'U' is not assignable to type 'T'. | ||
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'U'. | ||
} |
17 changes: 17 additions & 0 deletions
17
tests/baselines/reference/conditionalTypeVarianceBigArrayConstraintsPerformance.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
//// [conditionalTypeVarianceBigArrayConstraintsPerformance.ts] | ||
/// <reference path="/.lib/react16.d.ts" /> | ||
|
||
type Stuff<T> = | ||
T extends keyof JSX.IntrinsicElements | ||
? JSX.IntrinsicElements[T] | ||
: any; | ||
|
||
function F<T, U>(p1: Stuff<T>, p2: Stuff<U>) { | ||
p1 = p2; // Error | ||
} | ||
|
||
//// [conditionalTypeVarianceBigArrayConstraintsPerformance.js] | ||
/// <reference path="react16.d.ts" /> | ||
function F(p1, p2) { | ||
p1 = p2; // Error | ||
} |
34 changes: 34 additions & 0 deletions
34
tests/baselines/reference/conditionalTypeVarianceBigArrayConstraintsPerformance.symbols
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
=== tests/cases/compiler/conditionalTypeVarianceBigArrayConstraintsPerformance.ts === | ||
/// <reference path="react16.d.ts" /> | ||
|
||
type Stuff<T> = | ||
>Stuff : Symbol(Stuff, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 0, 0)) | ||
>T : Symbol(T, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 2, 11)) | ||
|
||
T extends keyof JSX.IntrinsicElements | ||
>T : Symbol(T, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 2, 11)) | ||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12)) | ||
>IntrinsicElements : Symbol(JSX.IntrinsicElements, Decl(react16.d.ts, 2514, 86)) | ||
|
||
? JSX.IntrinsicElements[T] | ||
>JSX : Symbol(JSX, Decl(react16.d.ts, 2493, 12)) | ||
>IntrinsicElements : Symbol(JSX.IntrinsicElements, Decl(react16.d.ts, 2514, 86)) | ||
>T : Symbol(T, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 2, 11)) | ||
|
||
: any; | ||
|
||
function F<T, U>(p1: Stuff<T>, p2: Stuff<U>) { | ||
>F : Symbol(F, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 5, 14)) | ||
>T : Symbol(T, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 11)) | ||
>U : Symbol(U, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 13)) | ||
>p1 : Symbol(p1, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 17)) | ||
>Stuff : Symbol(Stuff, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 0, 0)) | ||
>T : Symbol(T, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 11)) | ||
>p2 : Symbol(p2, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 30)) | ||
>Stuff : Symbol(Stuff, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 0, 0)) | ||
>U : Symbol(U, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 13)) | ||
|
||
p1 = p2; // Error | ||
>p1 : Symbol(p1, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 17)) | ||
>p2 : Symbol(p2, Decl(conditionalTypeVarianceBigArrayConstraintsPerformance.ts, 7, 30)) | ||
} |
24 changes: 24 additions & 0 deletions
24
tests/baselines/reference/conditionalTypeVarianceBigArrayConstraintsPerformance.types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
=== tests/cases/compiler/conditionalTypeVarianceBigArrayConstraintsPerformance.ts === | ||
/// <reference path="react16.d.ts" /> | ||
|
||
type Stuff<T> = | ||
>Stuff : Stuff<T> | ||
|
||
T extends keyof JSX.IntrinsicElements | ||
>JSX : any | ||
|
||
? JSX.IntrinsicElements[T] | ||
>JSX : any | ||
|
||
: any; | ||
|
||
function F<T, U>(p1: Stuff<T>, p2: Stuff<U>) { | ||
>F : <T, U>(p1: Stuff<T>, p2: Stuff<U>) => void | ||
>p1 : Stuff<T> | ||
>p2 : Stuff<U> | ||
|
||
p1 = p2; // Error | ||
>p1 = p2 : Stuff<U> | ||
>p1 : Stuff<T> | ||
>p2 : Stuff<U> | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
tests/cases/compiler/deepComparisons.ts(2,9): error TS2322: Type 'T' is not assignable to type 'Extract<T, string>'. | ||
tests/cases/compiler/deepComparisons.ts(3,9): error TS2322: Type 'T[K1]' is not assignable to type 'Extract<T[K1], string>'. | ||
Type 'T[keyof T]' is not assignable to type 'Extract<T[K1], string>'. | ||
Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'Extract<T[K1], string>'. | ||
Type 'T[string]' is not assignable to type 'Extract<T[K1], string>'. | ||
tests/cases/compiler/deepComparisons.ts(4,9): error TS2322: Type 'T[K1][K2]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
Type 'T[K1][keyof T[K1]]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
Type 'T[K1][string] | T[K1][number] | T[K1][symbol]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
Type 'T[K1][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
Type 'T[keyof T][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
Type 'T[string][string] | T[number][string] | T[symbol][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
Type 'T[string][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
|
||
|
||
==== tests/cases/compiler/deepComparisons.ts (3 errors) ==== | ||
function f1<T, K1 extends keyof T, K2 extends keyof T[K1]>() { | ||
let v1: Extract<T, string> = 0 as any as T; // Error | ||
~~ | ||
!!! error TS2322: Type 'T' is not assignable to type 'Extract<T, string>'. | ||
let v2: Extract<T[K1], string> = 0 as any as T[K1]; // Error | ||
~~ | ||
!!! error TS2322: Type 'T[K1]' is not assignable to type 'Extract<T[K1], string>'. | ||
!!! error TS2322: Type 'T[keyof T]' is not assignable to type 'Extract<T[K1], string>'. | ||
!!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'Extract<T[K1], string>'. | ||
!!! error TS2322: Type 'T[string]' is not assignable to type 'Extract<T[K1], string>'. | ||
let v3: Extract<T[K1][K2], string> = 0 as any as T[K1][K2]; // No error | ||
~~ | ||
!!! error TS2322: Type 'T[K1][K2]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
!!! error TS2322: Type 'T[K1][keyof T[K1]]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
!!! error TS2322: Type 'T[K1][string] | T[K1][number] | T[K1][symbol]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
!!! error TS2322: Type 'T[K1][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
!!! error TS2322: Type 'T[keyof T][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
!!! error TS2322: Type 'T[string][string] | T[number][string] | T[symbol][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
!!! error TS2322: Type 'T[string][string]' is not assignable to type 'Extract<T[K1][K2], string>'. | ||
} | ||
|
||
type Foo<T> = { x: Foo<T> }; | ||
type Bar<T> = { x: Bar<T[]> }; | ||
|
||
function f2<U>() { | ||
let x: Foo<U> = 0 as any as Bar<U>; // Error, excessive stack depth | ||
} | ||
|
||
type Foo1<T> = { x: Foo2<T> }; | ||
type Foo2<T> = { x: Foo1<T> }; | ||
|
||
function f3<U>() { | ||
let x: Foo1<U> = 0 as any as Bar<U>; // No error! | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
//// [deepComparisons.ts] | ||
function f1<T, K1 extends keyof T, K2 extends keyof T[K1]>() { | ||
let v1: Extract<T, string> = 0 as any as T; // Error | ||
let v2: Extract<T[K1], string> = 0 as any as T[K1]; // Error | ||
let v3: Extract<T[K1][K2], string> = 0 as any as T[K1][K2]; // No error | ||
} | ||
|
||
type Foo<T> = { x: Foo<T> }; | ||
type Bar<T> = { x: Bar<T[]> }; | ||
|
||
function f2<U>() { | ||
let x: Foo<U> = 0 as any as Bar<U>; // Error, excessive stack depth | ||
} | ||
|
||
type Foo1<T> = { x: Foo2<T> }; | ||
type Foo2<T> = { x: Foo1<T> }; | ||
|
||
function f3<U>() { | ||
let x: Foo1<U> = 0 as any as Bar<U>; // No error! | ||
} | ||
|
||
//// [deepComparisons.js] | ||
function f1() { | ||
var v1 = 0; // Error | ||
var v2 = 0; // Error | ||
var v3 = 0; // No error | ||
} | ||
function f2() { | ||
var x = 0; // Error, excessive stack depth | ||
} | ||
function f3() { | ||
var x = 0; // No error! | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
=== tests/cases/compiler/deepComparisons.ts === | ||
function f1<T, K1 extends keyof T, K2 extends keyof T[K1]>() { | ||
>f1 : Symbol(f1, Decl(deepComparisons.ts, 0, 0)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>K1 : Symbol(K1, Decl(deepComparisons.ts, 0, 14)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>K2 : Symbol(K2, Decl(deepComparisons.ts, 0, 34)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>K1 : Symbol(K1, Decl(deepComparisons.ts, 0, 14)) | ||
|
||
let v1: Extract<T, string> = 0 as any as T; // Error | ||
>v1 : Symbol(v1, Decl(deepComparisons.ts, 1, 7)) | ||
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
|
||
let v2: Extract<T[K1], string> = 0 as any as T[K1]; // Error | ||
>v2 : Symbol(v2, Decl(deepComparisons.ts, 2, 7)) | ||
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>K1 : Symbol(K1, Decl(deepComparisons.ts, 0, 14)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>K1 : Symbol(K1, Decl(deepComparisons.ts, 0, 14)) | ||
|
||
let v3: Extract<T[K1][K2], string> = 0 as any as T[K1][K2]; // No error | ||
>v3 : Symbol(v3, Decl(deepComparisons.ts, 3, 7)) | ||
>Extract : Symbol(Extract, Decl(lib.es5.d.ts, --, --)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>K1 : Symbol(K1, Decl(deepComparisons.ts, 0, 14)) | ||
>K2 : Symbol(K2, Decl(deepComparisons.ts, 0, 34)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 0, 12)) | ||
>K1 : Symbol(K1, Decl(deepComparisons.ts, 0, 14)) | ||
>K2 : Symbol(K2, Decl(deepComparisons.ts, 0, 34)) | ||
} | ||
|
||
type Foo<T> = { x: Foo<T> }; | ||
>Foo : Symbol(Foo, Decl(deepComparisons.ts, 4, 1)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 6, 9)) | ||
>x : Symbol(x, Decl(deepComparisons.ts, 6, 15)) | ||
>Foo : Symbol(Foo, Decl(deepComparisons.ts, 4, 1)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 6, 9)) | ||
|
||
type Bar<T> = { x: Bar<T[]> }; | ||
>Bar : Symbol(Bar, Decl(deepComparisons.ts, 6, 28)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 7, 9)) | ||
>x : Symbol(x, Decl(deepComparisons.ts, 7, 15)) | ||
>Bar : Symbol(Bar, Decl(deepComparisons.ts, 6, 28)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 7, 9)) | ||
|
||
function f2<U>() { | ||
>f2 : Symbol(f2, Decl(deepComparisons.ts, 7, 30)) | ||
>U : Symbol(U, Decl(deepComparisons.ts, 9, 12)) | ||
|
||
let x: Foo<U> = 0 as any as Bar<U>; // Error, excessive stack depth | ||
>x : Symbol(x, Decl(deepComparisons.ts, 10, 7)) | ||
>Foo : Symbol(Foo, Decl(deepComparisons.ts, 4, 1)) | ||
>U : Symbol(U, Decl(deepComparisons.ts, 9, 12)) | ||
>Bar : Symbol(Bar, Decl(deepComparisons.ts, 6, 28)) | ||
>U : Symbol(U, Decl(deepComparisons.ts, 9, 12)) | ||
} | ||
|
||
type Foo1<T> = { x: Foo2<T> }; | ||
>Foo1 : Symbol(Foo1, Decl(deepComparisons.ts, 11, 1)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 13, 10)) | ||
>x : Symbol(x, Decl(deepComparisons.ts, 13, 16)) | ||
>Foo2 : Symbol(Foo2, Decl(deepComparisons.ts, 13, 30)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 13, 10)) | ||
|
||
type Foo2<T> = { x: Foo1<T> }; | ||
>Foo2 : Symbol(Foo2, Decl(deepComparisons.ts, 13, 30)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 14, 10)) | ||
>x : Symbol(x, Decl(deepComparisons.ts, 14, 16)) | ||
>Foo1 : Symbol(Foo1, Decl(deepComparisons.ts, 11, 1)) | ||
>T : Symbol(T, Decl(deepComparisons.ts, 14, 10)) | ||
|
||
function f3<U>() { | ||
>f3 : Symbol(f3, Decl(deepComparisons.ts, 14, 30)) | ||
>U : Symbol(U, Decl(deepComparisons.ts, 16, 12)) | ||
|
||
let x: Foo1<U> = 0 as any as Bar<U>; // No error! | ||
>x : Symbol(x, Decl(deepComparisons.ts, 17, 7)) | ||
>Foo1 : Symbol(Foo1, Decl(deepComparisons.ts, 11, 1)) | ||
>U : Symbol(U, Decl(deepComparisons.ts, 16, 12)) | ||
>Bar : Symbol(Bar, Decl(deepComparisons.ts, 6, 28)) | ||
>U : Symbol(U, Decl(deepComparisons.ts, 16, 12)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
=== tests/cases/compiler/deepComparisons.ts === | ||
function f1<T, K1 extends keyof T, K2 extends keyof T[K1]>() { | ||
>f1 : <T, K1 extends keyof T, K2 extends keyof T[K1]>() => void | ||
|
||
let v1: Extract<T, string> = 0 as any as T; // Error | ||
>v1 : Extract<T, string> | ||
>0 as any as T : T | ||
>0 as any : any | ||
>0 : 0 | ||
|
||
let v2: Extract<T[K1], string> = 0 as any as T[K1]; // Error | ||
>v2 : Extract<T[K1], string> | ||
>0 as any as T[K1] : T[K1] | ||
>0 as any : any | ||
>0 : 0 | ||
|
||
let v3: Extract<T[K1][K2], string> = 0 as any as T[K1][K2]; // No error | ||
>v3 : Extract<T[K1][K2], string> | ||
>0 as any as T[K1][K2] : T[K1][K2] | ||
>0 as any : any | ||
>0 : 0 | ||
} | ||
|
||
type Foo<T> = { x: Foo<T> }; | ||
>Foo : Foo<T> | ||
>x : Foo<T> | ||
|
||
type Bar<T> = { x: Bar<T[]> }; | ||
>Bar : Bar<T> | ||
>x : Bar<T[]> | ||
|
||
function f2<U>() { | ||
>f2 : <U>() => void | ||
|
||
let x: Foo<U> = 0 as any as Bar<U>; // Error, excessive stack depth | ||
>x : Foo<U> | ||
>0 as any as Bar<U> : Bar<U> | ||
>0 as any : any | ||
>0 : 0 | ||
} | ||
|
||
type Foo1<T> = { x: Foo2<T> }; | ||
>Foo1 : Foo1<T> | ||
>x : Foo2<T> | ||
|
||
type Foo2<T> = { x: Foo1<T> }; | ||
>Foo2 : Foo2<T> | ||
>x : Foo1<T> | ||
|
||
function f3<U>() { | ||
>f3 : <U>() => void | ||
|
||
let x: Foo1<U> = 0 as any as Bar<U>; // No error! | ||
>x : Foo1<U> | ||
>0 as any as Bar<U> : Bar<U> | ||
>0 as any : any | ||
>0 : 0 | ||
} |
28 changes: 28 additions & 0 deletions
28
tests/baselines/reference/genericCapturingFunctionNarrowing.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
//// [genericCapturingFunctionNarrowing.ts] | ||
function needsToNarrowTheType<First extends { foo: string }, Second extends { bar: string }, SubFirst extends First, SubFirstMore extends First & {other: string}>(thing: First | SubFirst | SubFirstMore | Second) { | ||
if (hasAFoo(thing)) { | ||
console.log(thing.foo); | ||
} | ||
else { | ||
// I would expect this to work because the type should be narrowed in this branch to `Second` | ||
console.log(thing.bar); // Error: Property 'bar' does not exist on type 'First | Second'. | ||
} | ||
|
||
function hasAFoo(value: First | Second): value is First { | ||
return "foo" in value; | ||
} | ||
} | ||
|
||
//// [genericCapturingFunctionNarrowing.js] | ||
function needsToNarrowTheType(thing) { | ||
if (hasAFoo(thing)) { | ||
console.log(thing.foo); | ||
} | ||
else { | ||
// I would expect this to work because the type should be narrowed in this branch to `Second` | ||
console.log(thing.bar); // Error: Property 'bar' does not exist on type 'First | Second'. | ||
} | ||
function hasAFoo(value) { | ||
return "foo" in value; | ||
} | ||
} |
Oops, something went wrong.