Properly compute SymbolFlags.Optional for intersected properties (#50958)

* `in` proves property presence only if property can't be undefined

* Accept new baselines

* Add tests

* Accept new baselines

* Properly compute SymbolFlags.Optional for intersected properties

* Accept new baselines

* Check optionality only for property-like declarations

* Add more tests
This commit is contained in:
Anders Hejlsberg 2022-09-29 15:18:21 -07:00 committed by GitHub
parent d1586de043
commit ecf50e81a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1014 additions and 52 deletions

View File

@ -12566,7 +12566,7 @@ namespace ts {
let indexTypes: Type[] | undefined;
const isUnion = containingType.flags & TypeFlags.Union;
// Flags we want to propagate to the result if they exist in all source symbols
let optionalFlag = isUnion ? SymbolFlags.None : SymbolFlags.Optional;
let optionalFlag: SymbolFlags | undefined;
let syntheticFlag = CheckFlags.SyntheticMethod;
let checkFlags = isUnion ? 0 : CheckFlags.Readonly;
let mergedInstantiations = false;
@ -12576,11 +12576,14 @@ namespace ts {
const prop = getPropertyOfType(type, name, skipObjectFunctionPropertyAugment);
const modifiers = prop ? getDeclarationModifierFlagsFromSymbol(prop) : 0;
if (prop) {
if (isUnion) {
optionalFlag |= (prop.flags & SymbolFlags.Optional);
}
else {
optionalFlag &= prop.flags;
if (prop.flags & SymbolFlags.ClassMember) {
optionalFlag ??= isUnion ? SymbolFlags.None : SymbolFlags.Optional;
if (isUnion) {
optionalFlag |= (prop.flags & SymbolFlags.Optional);
}
else {
optionalFlag &= prop.flags;
}
}
if (!singleProp) {
singleProp = prop;
@ -12699,7 +12702,7 @@ namespace ts {
propTypes.push(type);
}
addRange(propTypes, indexTypes);
const result = createSymbol(SymbolFlags.Property | optionalFlag, name, syntheticFlag | checkFlags);
const result = createSymbol(SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags);
result.containingType = containingType;
if (!hasNonUniformValueDeclaration && firstValueDeclaration) {
result.valueDeclaration = firstValueDeclaration;
@ -20455,7 +20458,7 @@ namespace ts {
return Ternary.False;
}
// When checking for comparability, be more lenient with optional properties.
if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && !(targetProp.flags & SymbolFlags.Optional)) {
if (!skipOptional && sourceProp.flags & SymbolFlags.Optional && targetProp.flags & SymbolFlags.ClassMember && !(targetProp.flags & SymbolFlags.Optional)) {
// TypeScript 1.0 spec (April 2014): 3.8.3
// S is a subtype of a type T, and T is a supertype of S if ...
// S' and T are object types and, for each member M in T..

View File

@ -21,14 +21,13 @@ tests/cases/compiler/inKeywordTypeguard.ts(74,32): error TS2339: Property 'a' do
tests/cases/compiler/inKeywordTypeguard.ts(82,39): error TS2339: Property 'b' does not exist on type 'A'.
tests/cases/compiler/inKeywordTypeguard.ts(84,39): error TS2339: Property 'a' does not exist on type 'B'.
tests/cases/compiler/inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' does not exist on type 'never'.
tests/cases/compiler/inKeywordTypeguard.ts(150,16): error TS2339: Property 'ontouchstart' does not exist on type 'never'.
tests/cases/compiler/inKeywordTypeguard.ts(155,16): error TS2322: Type 'unknown' is not assignable to type 'object'.
tests/cases/compiler/inKeywordTypeguard.ts(158,21): error TS2322: Type 'unknown' is not assignable to type 'object'.
tests/cases/compiler/inKeywordTypeguard.ts(183,16): error TS2322: Type 'T' is not assignable to type 'object'.
tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2322: Type 'T' is not assignable to type 'object'.
==== tests/cases/compiler/inKeywordTypeguard.ts (22 errors) ====
==== tests/cases/compiler/inKeywordTypeguard.ts (21 errors) ====
class A { a: string; }
class B { b: string; }
@ -219,8 +218,6 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2322: Type 'T' is no
window.ontouchstart
} else {
window.ontouchstart
~~~~~~~~~~~~
!!! error TS2339: Property 'ontouchstart' does not exist on type 'never'.
}
}
@ -353,6 +350,64 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2322: Type 'T' is no
}
}
function f10(x: { a: unknown }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f11(x: { a: any }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f12(x: { a: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f13(x: { a?: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f14(x: { a: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f15(x: { a?: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
x = y;
}
// Repro from #50639
function foo<A>(value: A) {
@ -360,4 +415,9 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2322: Type 'T' is no
value; // A & object & Record<"prop", unknown>
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;

View File

@ -271,6 +271,64 @@ function f9(x: object) {
}
}
function f10(x: { a: unknown }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f11(x: { a: any }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f12(x: { a: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f13(x: { a?: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f14(x: { a: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f15(x: { a?: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
x = y;
}
// Repro from #50639
function foo<A>(value: A) {
@ -278,6 +336,11 @@ function foo<A>(value: A) {
value; // A & object & Record<"prop", unknown>
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
//// [inKeywordTypeguard.js]
@ -533,9 +596,62 @@ function f9(x) {
x[sym];
}
}
function f10(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f11(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f12(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f13(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f14(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f15(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f16(x, y) {
x = y;
}
// Repro from #50639
function foo(value) {
if (typeof value === "object" && value !== null && "prop" in value) {
value; // A & object & Record<"prop", unknown>
}
}
// Repro from #50954
const checkIsTouchDevice = () => "ontouchstart" in window || "msMaxTouchPoints" in window.navigator;

View File

@ -371,7 +371,9 @@ function negativeIntersectionTest() {
} else {
window.ontouchstart
>window.ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
}
}
@ -707,21 +709,147 @@ function f9(x: object) {
}
}
// Repro from #50639
function f10(x: { a: unknown }) {
>f10 : Symbol(f10, Decl(inKeywordTypeguard.ts, 270, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 272, 17))
function foo<A>(value: A) {
>foo : Symbol(foo, Decl(inKeywordTypeguard.ts, 270, 1))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 274, 13))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 274, 13))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
if (typeof value === "object" && value !== null && "prop" in value) {
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
value; // A & object & Record<"prop", unknown>
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
}
}
function f11(x: { a: any }) {
>f11 : Symbol(f11, Decl(inKeywordTypeguard.ts, 279, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 281, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
}
}
function f12(x: { a: string }) {
>f12 : Symbol(f12, Decl(inKeywordTypeguard.ts, 288, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 290, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
}
}
function f13(x: { a?: string }) {
>f13 : Symbol(f13, Decl(inKeywordTypeguard.ts, 297, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 299, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
}
}
function f14(x: { a: string | undefined }) {
>f14 : Symbol(f14, Decl(inKeywordTypeguard.ts, 306, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 308, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
}
}
function f15(x: { a?: string | undefined }) {
>f15 : Symbol(f15, Decl(inKeywordTypeguard.ts, 315, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 317, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
>f16 : Symbol(f16, Decl(inKeywordTypeguard.ts, 324, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 326, 13))
>globalThis : Symbol(globalThis)
>y : Symbol(y, Decl(inKeywordTypeguard.ts, 326, 34))
>Window : Symbol(Window, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>globalThis : Symbol(globalThis)
x = y;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 326, 13))
>y : Symbol(y, Decl(inKeywordTypeguard.ts, 326, 34))
}
// Repro from #50639
function foo<A>(value: A) {
>foo : Symbol(foo, Decl(inKeywordTypeguard.ts, 328, 1))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 332, 13))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 332, 13))
if (typeof value === "object" && value !== null && "prop" in value) {
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
value; // A & object & Record<"prop", unknown>
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
>checkIsTouchDevice : Symbol(checkIsTouchDevice, Decl(inKeywordTypeguard.ts, 340, 5))
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>window.navigator : Symbol(navigator, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>navigator : Symbol(navigator, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))

View File

@ -446,9 +446,9 @@ function negativeIntersectionTest() {
} else {
window.ontouchstart
>window.ontouchstart : any
>window : never
>ontouchstart : any
>window.ontouchstart : ((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)
>window : Window & typeof globalThis
>ontouchstart : ((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)
}
}
@ -887,6 +887,133 @@ function f9(x: object) {
}
}
function f10(x: { a: unknown }) {
>f10 : (x: { a: unknown;}) => void
>x : { a: unknown; }
>a : unknown
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: unknown; }
x;
>x : { a: unknown; }
}
else {
x;
>x : never
}
}
function f11(x: { a: any }) {
>f11 : (x: { a: any;}) => void
>x : { a: any; }
>a : any
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: any; }
x;
>x : { a: any; }
}
else {
x;
>x : never
}
}
function f12(x: { a: string }) {
>f12 : (x: { a: string;}) => void
>x : { a: string; }
>a : string
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: string; }
x;
>x : { a: string; }
}
else {
x;
>x : never
}
}
function f13(x: { a?: string }) {
>f13 : (x: { a?: string;}) => void
>x : { a?: string; }
>a : string
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a?: string; }
x;
>x : { a?: string; }
}
else {
x;
>x : { a?: string; }
}
}
function f14(x: { a: string | undefined }) {
>f14 : (x: { a: string | undefined;}) => void
>x : { a: string | undefined; }
>a : string
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: string; }
x;
>x : { a: string; }
}
else {
x;
>x : never
}
}
function f15(x: { a?: string | undefined }) {
>f15 : (x: { a?: string | undefined;}) => void
>x : { a?: string | undefined; }
>a : string
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a?: string; }
x;
>x : { a?: string; }
}
else {
x;
>x : { a?: string; }
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
>f16 : (x: typeof globalThis, y: Window & typeof globalThis) => void
>x : typeof globalThis
>globalThis : typeof globalThis
>y : Window & typeof globalThis
>globalThis : typeof globalThis
x = y;
>x = y : Window & typeof globalThis
>x : typeof globalThis
>y : Window & typeof globalThis
}
// Repro from #50639
function foo<A>(value: A) {
@ -912,3 +1039,20 @@ function foo<A>(value: A) {
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
>checkIsTouchDevice : () => boolean
>() => "ontouchstart" in window || "msMaxTouchPoints" in window.navigator : () => boolean
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
>"ontouchstart" in window || "msMaxTouchPoints" in window.navigator : boolean
>"ontouchstart" in window : boolean
>"ontouchstart" : "ontouchstart"
>window : Window & typeof globalThis
>"msMaxTouchPoints" in window.navigator : boolean
>"msMaxTouchPoints" : "msMaxTouchPoints"
>window.navigator : Navigator
>window : Window & typeof globalThis
>navigator : Navigator

View File

@ -28,14 +28,13 @@ tests/cases/compiler/inKeywordTypeguard.ts(82,39): error TS2339: Property 'b' do
tests/cases/compiler/inKeywordTypeguard.ts(84,39): error TS2339: Property 'a' does not exist on type 'B'.
tests/cases/compiler/inKeywordTypeguard.ts(90,5): error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
tests/cases/compiler/inKeywordTypeguard.ts(94,26): error TS2339: Property 'a' does not exist on type 'never'.
tests/cases/compiler/inKeywordTypeguard.ts(150,16): error TS2339: Property 'ontouchstart' does not exist on type 'never'.
tests/cases/compiler/inKeywordTypeguard.ts(155,16): error TS18046: 'x' is of type 'unknown'.
tests/cases/compiler/inKeywordTypeguard.ts(158,21): error TS2638: Type '{}' may represent a primitive value, which is not permitted as the right operand of the 'in' operator.
tests/cases/compiler/inKeywordTypeguard.ts(183,16): error TS2322: Type 'T' is not assignable to type 'object'.
tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNullable<T>' may represent a primitive value, which is not permitted as the right operand of the 'in' operator.
==== tests/cases/compiler/inKeywordTypeguard.ts (29 errors) ====
==== tests/cases/compiler/inKeywordTypeguard.ts (28 errors) ====
class A { a: string; }
~
!!! error TS2564: Property 'a' has no initializer and is not definitely assigned in the constructor.
@ -240,8 +239,6 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNulla
window.ontouchstart
} else {
window.ontouchstart
~~~~~~~~~~~~
!!! error TS2339: Property 'ontouchstart' does not exist on type 'never'.
}
}
@ -373,6 +370,64 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNulla
}
}
function f10(x: { a: unknown }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f11(x: { a: any }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f12(x: { a: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f13(x: { a?: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f14(x: { a: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f15(x: { a?: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
x = y;
}
// Repro from #50639
function foo<A>(value: A) {
@ -380,4 +435,9 @@ tests/cases/compiler/inKeywordTypeguard.ts(186,21): error TS2638: Type 'NonNulla
value; // A & object & Record<"prop", unknown>
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;

View File

@ -271,6 +271,64 @@ function f9(x: object) {
}
}
function f10(x: { a: unknown }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f11(x: { a: any }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f12(x: { a: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f13(x: { a?: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f14(x: { a: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f15(x: { a?: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
x = y;
}
// Repro from #50639
function foo<A>(value: A) {
@ -278,6 +336,11 @@ function foo<A>(value: A) {
value; // A & object & Record<"prop", unknown>
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
//// [inKeywordTypeguard.js]
@ -534,9 +597,62 @@ function f9(x) {
x[sym];
}
}
function f10(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f11(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f12(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f13(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f14(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f15(x) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f16(x, y) {
x = y;
}
// Repro from #50639
function foo(value) {
if (typeof value === "object" && value !== null && "prop" in value) {
value; // A & object & Record<"prop", unknown>
}
}
// Repro from #50954
const checkIsTouchDevice = () => "ontouchstart" in window || "msMaxTouchPoints" in window.navigator;

View File

@ -371,7 +371,9 @@ function negativeIntersectionTest() {
} else {
window.ontouchstart
>window.ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>ontouchstart : Symbol(ontouchstart, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
}
}
@ -707,21 +709,147 @@ function f9(x: object) {
}
}
// Repro from #50639
function f10(x: { a: unknown }) {
>f10 : Symbol(f10, Decl(inKeywordTypeguard.ts, 270, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 272, 17))
function foo<A>(value: A) {
>foo : Symbol(foo, Decl(inKeywordTypeguard.ts, 270, 1))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 274, 13))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 274, 13))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
if (typeof value === "object" && value !== null && "prop" in value) {
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
value; // A & object & Record<"prop", unknown>
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 274, 16))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 272, 13))
}
}
function f11(x: { a: any }) {
>f11 : Symbol(f11, Decl(inKeywordTypeguard.ts, 279, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 281, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 281, 13))
}
}
function f12(x: { a: string }) {
>f12 : Symbol(f12, Decl(inKeywordTypeguard.ts, 288, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 290, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 290, 13))
}
}
function f13(x: { a?: string }) {
>f13 : Symbol(f13, Decl(inKeywordTypeguard.ts, 297, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 299, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 299, 13))
}
}
function f14(x: { a: string | undefined }) {
>f14 : Symbol(f14, Decl(inKeywordTypeguard.ts, 306, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 308, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 308, 13))
}
}
function f15(x: { a?: string | undefined }) {
>f15 : Symbol(f15, Decl(inKeywordTypeguard.ts, 315, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
>a : Symbol(a, Decl(inKeywordTypeguard.ts, 317, 17))
if ("a" in x) {
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
}
else {
x;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 317, 13))
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
>f16 : Symbol(f16, Decl(inKeywordTypeguard.ts, 324, 1))
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 326, 13))
>globalThis : Symbol(globalThis)
>y : Symbol(y, Decl(inKeywordTypeguard.ts, 326, 34))
>Window : Symbol(Window, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>globalThis : Symbol(globalThis)
x = y;
>x : Symbol(x, Decl(inKeywordTypeguard.ts, 326, 13))
>y : Symbol(y, Decl(inKeywordTypeguard.ts, 326, 34))
}
// Repro from #50639
function foo<A>(value: A) {
>foo : Symbol(foo, Decl(inKeywordTypeguard.ts, 328, 1))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 332, 13))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
>A : Symbol(A, Decl(inKeywordTypeguard.ts, 332, 13))
if (typeof value === "object" && value !== null && "prop" in value) {
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
value; // A & object & Record<"prop", unknown>
>value : Symbol(value, Decl(inKeywordTypeguard.ts, 332, 16))
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
>checkIsTouchDevice : Symbol(checkIsTouchDevice, Decl(inKeywordTypeguard.ts, 340, 5))
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>window.navigator : Symbol(navigator, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>navigator : Symbol(navigator, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))

View File

@ -446,9 +446,9 @@ function negativeIntersectionTest() {
} else {
window.ontouchstart
>window.ontouchstart : any
>window : never
>ontouchstart : any
>window.ontouchstart : (((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)) | null | undefined
>window : Window & typeof globalThis
>ontouchstart : (((this: GlobalEventHandlers, ev: TouchEvent) => any) & ((this: Window, ev: TouchEvent) => any)) | null | undefined
}
}
@ -887,6 +887,133 @@ function f9(x: object) {
}
}
function f10(x: { a: unknown }) {
>f10 : (x: { a: unknown;}) => void
>x : { a: unknown; }
>a : unknown
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: unknown; }
x;
>x : { a: unknown; }
}
else {
x;
>x : never
}
}
function f11(x: { a: any }) {
>f11 : (x: { a: any;}) => void
>x : { a: any; }
>a : any
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: any; }
x;
>x : { a: any; }
}
else {
x;
>x : never
}
}
function f12(x: { a: string }) {
>f12 : (x: { a: string;}) => void
>x : { a: string; }
>a : string
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: string; }
x;
>x : { a: string; }
}
else {
x;
>x : never
}
}
function f13(x: { a?: string }) {
>f13 : (x: { a?: string;}) => void
>x : { a?: string | undefined; }
>a : string | undefined
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a?: string | undefined; }
x;
>x : { a?: string | undefined; }
}
else {
x;
>x : { a?: string | undefined; }
}
}
function f14(x: { a: string | undefined }) {
>f14 : (x: { a: string | undefined;}) => void
>x : { a: string | undefined; }
>a : string | undefined
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a: string | undefined; }
x;
>x : { a: string | undefined; }
}
else {
x;
>x : never
}
}
function f15(x: { a?: string | undefined }) {
>f15 : (x: { a?: string | undefined;}) => void
>x : { a?: string | undefined; }
>a : string | undefined
if ("a" in x) {
>"a" in x : boolean
>"a" : "a"
>x : { a?: string | undefined; }
x;
>x : { a?: string | undefined; }
}
else {
x;
>x : { a?: string | undefined; }
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
>f16 : (x: typeof globalThis, y: Window & typeof globalThis) => void
>x : typeof globalThis
>globalThis : typeof globalThis
>y : Window & typeof globalThis
>globalThis : typeof globalThis
x = y;
>x = y : Window & typeof globalThis
>x : typeof globalThis
>y : Window & typeof globalThis
}
// Repro from #50639
function foo<A>(value: A) {
@ -912,3 +1039,20 @@ function foo<A>(value: A) {
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
>checkIsTouchDevice : () => boolean
>() => "ontouchstart" in window || "msMaxTouchPoints" in window.navigator : () => boolean
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;
>"ontouchstart" in window || "msMaxTouchPoints" in window.navigator : boolean
>"ontouchstart" in window : boolean
>"ontouchstart" : "ontouchstart"
>window : Window & typeof globalThis
>"msMaxTouchPoints" in window.navigator : boolean
>"msMaxTouchPoints" : "msMaxTouchPoints"
>window.navigator : Navigator
>window : Window & typeof globalThis
>navigator : Navigator

File diff suppressed because one or more lines are too long

View File

@ -273,6 +273,64 @@ function f9(x: object) {
}
}
function f10(x: { a: unknown }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f11(x: { a: any }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f12(x: { a: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f13(x: { a?: string }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f14(x: { a: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f15(x: { a?: string | undefined }) {
if ("a" in x) {
x;
}
else {
x;
}
}
function f16(x: typeof globalThis, y: Window & typeof globalThis) {
x = y;
}
// Repro from #50639
function foo<A>(value: A) {
@ -280,3 +338,8 @@ function foo<A>(value: A) {
value; // A & object & Record<"prop", unknown>
}
}
// Repro from #50954
const checkIsTouchDevice = () =>
"ontouchstart" in window || "msMaxTouchPoints" in window.navigator;