1/* 2* Copyright (c) Microsoft Corporation. All rights reserved. 3* Copyright (c) 2023 Huawei Device Co., Ltd. 4* Licensed under the Apache License, Version 2.0 (the "License"); 5* you may not use this file except in compliance with the License. 6* You may obtain a copy of the License at 7* 8* http://www.apache.org/licenses/LICENSE-2.0 9* 10* Unless required by applicable law or agreed to in writing, software 11* distributed under the License is distributed on an "AS IS" BASIS, 12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13* See the License for the specific language governing permissions and 14* limitations under the License. 15* 16* This file has been modified by Huawei to verify type inference by adding verification statements. 17*/ 18 19// === tests/cases/conformance/expressions/typeGuards/typeGuardOfFromPropNameInUnionType.ts === 20declare function AssertType(value:any, type:string):void; 21class A { a: string; } 22class B { b: number; } 23class C { b: Object; } 24class D { a: Date; } 25 26function namedClasses(x: A | B) { 27 if ("a" in x) { 28AssertType("a" in x, "boolean"); 29AssertType("a", "string"); 30AssertType(x, "union"); 31 32 x.a = "1"; 33AssertType(x.a = "1", "string"); 34AssertType(x.a, "string"); 35AssertType("1", "string"); 36 37 } else { 38 x.b = 1; 39AssertType(x.b = 1, "int"); 40AssertType(x.b, "number"); 41AssertType(1, "int"); 42 } 43} 44 45function multipleClasses(x: A | B | C | D) { 46 if ("a" in x) { 47AssertType("a" in x, "boolean"); 48AssertType("a", "string"); 49AssertType(x, "union"); 50 51 let y: string | Date = x.a; 52AssertType(y, "union"); 53AssertType(x.a, "union"); 54 55 } else { 56 let z: number | Object = x.b; 57AssertType(z, "union"); 58AssertType(x.b, "union"); 59 } 60} 61 62function anonymousClasses(x: { a: string; } | { b: number; }) { 63 if ("a" in x) { 64AssertType("a" in x, "boolean"); 65AssertType("a", "string"); 66AssertType(x, "union"); 67 68 let y: string = x.a; 69AssertType(y, "string"); 70AssertType(x.a, "string"); 71 72 } else { 73 let z: number = x.b; 74AssertType(z, "number"); 75AssertType(x.b, "number"); 76 } 77} 78 79class AWithOptionalProp { a?: string; } 80class BWithOptionalProp { b?: string; } 81 82function positiveTestClassesWithOptionalProperties(x: AWithOptionalProp | BWithOptionalProp) { 83 if ("a" in x) { 84AssertType("a" in x, "boolean"); 85AssertType("a", "string"); 86AssertType(x, "union"); 87 88 x.a = "1"; 89AssertType(x.a = "1", "string"); 90AssertType(x.a, "string"); 91AssertType("1", "string"); 92 93 } else { 94 const y: string = x instanceof AWithOptionalProp 95AssertType(y, "string"); 96AssertType(x instanceof AWithOptionalProp ? x.a : x.b, "string"); 97AssertType(x instanceof AWithOptionalProp, "boolean"); 98AssertType(x, "union"); 99AssertType(AWithOptionalProp, "typeof AWithOptionalProp"); 100 101 ? x.a 102AssertType(x.a, "string"); 103 104 : x.b 105AssertType(x.b, "string"); 106 } 107} 108 109function inParenthesizedExpression(x: A | B) { 110 if ("a" in (x)) { 111AssertType("a" in (x), "boolean"); 112AssertType("a", "string"); 113AssertType((x), "union"); 114AssertType(x, "union"); 115 116 let y: string = x.a; 117AssertType(y, "string"); 118AssertType(x.a, "string"); 119 120 } else { 121 let z: number = x.b; 122AssertType(z, "number"); 123AssertType(x.b, "number"); 124 } 125} 126 127class ClassWithUnionProp { prop: A | B; } 128 129function inProperty(x: ClassWithUnionProp) { 130 if ("a" in x.prop) { 131AssertType("a" in x.prop, "boolean"); 132AssertType("a", "string"); 133AssertType(x.prop, "union"); 134 135 let y: string = x.prop.a; 136AssertType(y, "string"); 137AssertType(x.prop.a, "string"); 138AssertType(x.prop, "A"); 139 140 } else { 141 let z: number = x.prop.b; 142AssertType(z, "number"); 143AssertType(x.prop.b, "number"); 144AssertType(x.prop, "B"); 145 } 146} 147 148class NestedClassWithProp { outer: ClassWithUnionProp; } 149 150function innestedProperty(x: NestedClassWithProp) { 151 if ("a" in x.outer.prop) { 152AssertType("a" in x.outer.prop, "boolean"); 153AssertType("a", "string"); 154AssertType(x.outer.prop, "union"); 155AssertType(x.outer, "ClassWithUnionProp"); 156 157 let y: string = x.outer.prop.a; 158AssertType(y, "string"); 159AssertType(x.outer.prop.a, "string"); 160AssertType(x.outer.prop, "A"); 161AssertType(x.outer, "ClassWithUnionProp"); 162 163 } else { 164 let z: number = x.outer.prop.b; 165AssertType(z, "number"); 166AssertType(x.outer.prop.b, "number"); 167AssertType(x.outer.prop, "B"); 168AssertType(x.outer, "ClassWithUnionProp"); 169 } 170} 171 172class InMemberOfClass { 173 protected prop: A | B; 174 inThis() { 175 if ("a" in this.prop) { 176AssertType("a" in this.prop, "boolean"); 177AssertType("a", "string"); 178AssertType(this.prop, "union"); 179AssertType(this, "this"); 180 181 let y: string = this.prop.a; 182AssertType(y, "string"); 183AssertType(this.prop.a, "string"); 184AssertType(this.prop, "A"); 185AssertType(this, "this"); 186 187 } else { 188 let z: number = this.prop.b; 189AssertType(z, "number"); 190AssertType(this.prop.b, "number"); 191AssertType(this.prop, "B"); 192AssertType(this, "this"); 193 } 194 } 195} 196 197// added for completeness 198class SelfAssert { 199 a: string; 200 inThis() { 201 if ("a" in this) { 202AssertType("a" in this, "boolean"); 203AssertType("a", "string"); 204AssertType(this, "this"); 205 206 let y: string = this.a; 207AssertType(y, "string"); 208AssertType(this.a, "string"); 209AssertType(this, "this"); 210 211 } else { 212 } 213 } 214} 215 216interface Indexed { 217 [s: string]: any; 218} 219 220function f(i: Indexed) { 221 if ("a" in i) { 222AssertType("a" in i, "boolean"); 223AssertType("a", "string"); 224AssertType(i, "Indexed"); 225 226AssertType(i.a, "any"); 227 return i.a; 228 } 229 else if ("b" in i) { 230AssertType("b" in i, "boolean"); 231AssertType("b", "string"); 232AssertType(i, "Indexed"); 233 234AssertType(i.b, "any"); 235 return i.b; 236 } 237AssertType("c" in i && i.c, "any"); 238AssertType("c" in i, "boolean"); 239AssertType("c", "string"); 240AssertType(i, "Indexed"); 241AssertType(i.c, "any"); 242 return "c" in i && i.c; 243} 244 245 246