diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5e9c72ec48319..3c48f03df8861 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -27001,7 +27001,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isTypePresencePossible(type: Type, propName: __String, assumeTrue: boolean) { const prop = getPropertyOfType(type, propName); return prop ? - !!(prop.flags & SymbolFlags.Optional) || assumeTrue : + !!(prop.flags & SymbolFlags.Optional || getCheckFlags(prop) & CheckFlags.Partial) || assumeTrue : !!getApplicableIndexInfoForName(type, propName) || !assumeTrue; } diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=false).errors.txt b/tests/baselines/reference/inKeywordTypeguard(strict=false).errors.txt index 7d8bd0bea9a4b..dd3d705b7fdb6 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=false).errors.txt +++ b/tests/baselines/reference/inKeywordTypeguard(strict=false).errors.txt @@ -432,4 +432,33 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2322: Type 'T' is no const f =

(a: P & {}) => { "foo" in a; }; + + // Repro from #53773 + + function test1>(obj: T) { + if (Array.isArray(obj) || 'length' in obj) { + obj; // T + } + else { + obj; // T + } + } + + function test2>(obj: T) { + if (Array.isArray(obj)) { + obj; // T & any[] + } + else { + obj; // T + } + } + + function test3>(obj: T) { + if ('length' in obj) { + obj; // T + } + else { + obj; // T + } + } \ No newline at end of file diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=false).js b/tests/baselines/reference/inKeywordTypeguard(strict=false).js index ae1ccbb43c5be..d42e84293a198 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=false).js +++ b/tests/baselines/reference/inKeywordTypeguard(strict=false).js @@ -353,6 +353,35 @@ function isHTMLTable(table: T): boolean { const f =

(a: P & {}) => { "foo" in a; }; + +// Repro from #53773 + +function test1>(obj: T) { + if (Array.isArray(obj) || 'length' in obj) { + obj; // T + } + else { + obj; // T + } +} + +function test2>(obj: T) { + if (Array.isArray(obj)) { + obj; // T & any[] + } + else { + obj; // T + } +} + +function test3>(obj: T) { + if ('length' in obj) { + obj; // T + } + else { + obj; // T + } +} //// [inKeywordTypeguard.js] @@ -675,3 +704,28 @@ function isHTMLTable(table) { const f = (a) => { "foo" in a; }; +// Repro from #53773 +function test1(obj) { + if (Array.isArray(obj) || 'length' in obj) { + obj; // T + } + else { + obj; // T + } +} +function test2(obj) { + if (Array.isArray(obj)) { + obj; // T & any[] + } + else { + obj; // T + } +} +function test3(obj) { + if ('length' in obj) { + obj; // T + } + else { + obj; // T + } +} diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=false).symbols b/tests/baselines/reference/inKeywordTypeguard(strict=false).symbols index 9444bf3fc988c..3cbb8f33cc072 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=false).symbols +++ b/tests/baselines/reference/inKeywordTypeguard(strict=false).symbols @@ -879,3 +879,69 @@ const f =

(a: P & {}) => { }; +// Repro from #53773 + +function test1>(obj: T) { +>test1 : Symbol(test1, Decl(inKeywordTypeguard.ts, 353, 2)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 357, 15)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 357, 15)) + + if (Array.isArray(obj) || 'length' in obj) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) + + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) + } + else { + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) + } +} + +function test2>(obj: T) { +>test2 : Symbol(test2, Decl(inKeywordTypeguard.ts, 364, 1)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 366, 15)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 366, 15)) + + if (Array.isArray(obj)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) + + obj; // T & any[] +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) + } + else { + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) + } +} + +function test3>(obj: T) { +>test3 : Symbol(test3, Decl(inKeywordTypeguard.ts, 373, 1)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 375, 15)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 375, 15)) + + if ('length' in obj) { +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) + + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) + } + else { + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) + } +} + diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=false).types b/tests/baselines/reference/inKeywordTypeguard(strict=false).types index 2135c94979733..4f69cf393b59c 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=false).types +++ b/tests/baselines/reference/inKeywordTypeguard(strict=false).types @@ -1085,3 +1085,67 @@ const f =

(a: P & {}) => { }; +// Repro from #53773 + +function test1>(obj: T) { +>test1 : >(obj: T) => void +>obj : T + + if (Array.isArray(obj) || 'length' in obj) { +>Array.isArray(obj) || 'length' in obj : boolean +>Array.isArray(obj) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>obj : any[] | Record +>'length' in obj : boolean +>'length' : "length" +>obj : T + + obj; // T +>obj : T + } + else { + obj; // T +>obj : T + } +} + +function test2>(obj: T) { +>test2 : >(obj: T) => void +>obj : T + + if (Array.isArray(obj)) { +>Array.isArray(obj) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>obj : any[] | Record + + obj; // T & any[] +>obj : T & any[] + } + else { + obj; // T +>obj : T + } +} + +function test3>(obj: T) { +>test3 : >(obj: T) => void +>obj : T + + if ('length' in obj) { +>'length' in obj : boolean +>'length' : "length" +>obj : T + + obj; // T +>obj : T + } + else { + obj; // T +>obj : T + } +} + diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt b/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt index d47a0718aac8a..f0c97560e5c0b 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt +++ b/tests/baselines/reference/inKeywordTypeguard(strict=true).errors.txt @@ -452,4 +452,33 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNulla const f =

(a: P & {}) => { "foo" in a; }; + + // Repro from #53773 + + function test1>(obj: T) { + if (Array.isArray(obj) || 'length' in obj) { + obj; // T + } + else { + obj; // T + } + } + + function test2>(obj: T) { + if (Array.isArray(obj)) { + obj; // T & any[] + } + else { + obj; // T + } + } + + function test3>(obj: T) { + if ('length' in obj) { + obj; // T + } + else { + obj; // T + } + } \ No newline at end of file diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=true).js b/tests/baselines/reference/inKeywordTypeguard(strict=true).js index 73b2cf77cae44..01bd93fe8526e 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=true).js +++ b/tests/baselines/reference/inKeywordTypeguard(strict=true).js @@ -353,6 +353,35 @@ function isHTMLTable(table: T): boolean { const f =

(a: P & {}) => { "foo" in a; }; + +// Repro from #53773 + +function test1>(obj: T) { + if (Array.isArray(obj) || 'length' in obj) { + obj; // T + } + else { + obj; // T + } +} + +function test2>(obj: T) { + if (Array.isArray(obj)) { + obj; // T & any[] + } + else { + obj; // T + } +} + +function test3>(obj: T) { + if ('length' in obj) { + obj; // T + } + else { + obj; // T + } +} //// [inKeywordTypeguard.js] @@ -676,3 +705,28 @@ function isHTMLTable(table) { const f = (a) => { "foo" in a; }; +// Repro from #53773 +function test1(obj) { + if (Array.isArray(obj) || 'length' in obj) { + obj; // T + } + else { + obj; // T + } +} +function test2(obj) { + if (Array.isArray(obj)) { + obj; // T & any[] + } + else { + obj; // T + } +} +function test3(obj) { + if ('length' in obj) { + obj; // T + } + else { + obj; // T + } +} diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=true).symbols b/tests/baselines/reference/inKeywordTypeguard(strict=true).symbols index 9444bf3fc988c..3cbb8f33cc072 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=true).symbols +++ b/tests/baselines/reference/inKeywordTypeguard(strict=true).symbols @@ -879,3 +879,69 @@ const f =

(a: P & {}) => { }; +// Repro from #53773 + +function test1>(obj: T) { +>test1 : Symbol(test1, Decl(inKeywordTypeguard.ts, 353, 2)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 357, 15)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 357, 15)) + + if (Array.isArray(obj) || 'length' in obj) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) + + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) + } + else { + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 357, 54)) + } +} + +function test2>(obj: T) { +>test2 : Symbol(test2, Decl(inKeywordTypeguard.ts, 364, 1)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 366, 15)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 366, 15)) + + if (Array.isArray(obj)) { +>Array.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) + + obj; // T & any[] +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) + } + else { + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 366, 54)) + } +} + +function test3>(obj: T) { +>test3 : Symbol(test3, Decl(inKeywordTypeguard.ts, 373, 1)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 375, 15)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) +>T : Symbol(T, Decl(inKeywordTypeguard.ts, 375, 15)) + + if ('length' in obj) { +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) + + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) + } + else { + obj; // T +>obj : Symbol(obj, Decl(inKeywordTypeguard.ts, 375, 54)) + } +} + diff --git a/tests/baselines/reference/inKeywordTypeguard(strict=true).types b/tests/baselines/reference/inKeywordTypeguard(strict=true).types index 830b053aab180..d2bb573370368 100644 --- a/tests/baselines/reference/inKeywordTypeguard(strict=true).types +++ b/tests/baselines/reference/inKeywordTypeguard(strict=true).types @@ -1085,3 +1085,67 @@ const f =

(a: P & {}) => { }; +// Repro from #53773 + +function test1>(obj: T) { +>test1 : >(obj: T) => void +>obj : T + + if (Array.isArray(obj) || 'length' in obj) { +>Array.isArray(obj) || 'length' in obj : boolean +>Array.isArray(obj) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>obj : any[] | Record +>'length' in obj : boolean +>'length' : "length" +>obj : T + + obj; // T +>obj : T + } + else { + obj; // T +>obj : T + } +} + +function test2>(obj: T) { +>test2 : >(obj: T) => void +>obj : T + + if (Array.isArray(obj)) { +>Array.isArray(obj) : boolean +>Array.isArray : (arg: any) => arg is any[] +>Array : ArrayConstructor +>isArray : (arg: any) => arg is any[] +>obj : any[] | Record + + obj; // T & any[] +>obj : T & any[] + } + else { + obj; // T +>obj : T + } +} + +function test3>(obj: T) { +>test3 : >(obj: T) => void +>obj : T + + if ('length' in obj) { +>'length' in obj : boolean +>'length' : "length" +>obj : T + + obj; // T +>obj : T + } + else { + obj; // T +>obj : T + } +} + diff --git a/tests/cases/compiler/inKeywordTypeguard.ts b/tests/cases/compiler/inKeywordTypeguard.ts index 0c74dcded90ba..26145d0c7d9c3 100644 --- a/tests/cases/compiler/inKeywordTypeguard.ts +++ b/tests/cases/compiler/inKeywordTypeguard.ts @@ -355,3 +355,32 @@ function isHTMLTable(table: T): boolean { const f =

(a: P & {}) => { "foo" in a; }; + +// Repro from #53773 + +function test1>(obj: T) { + if (Array.isArray(obj) || 'length' in obj) { + obj; // T + } + else { + obj; // T + } +} + +function test2>(obj: T) { + if (Array.isArray(obj)) { + obj; // T & any[] + } + else { + obj; // T + } +} + +function test3>(obj: T) { + if ('length' in obj) { + obj; // T + } + else { + obj; // T + } +}