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/controlFlow/typeGuardsNestedAssignments.ts === 20declare function AssertType(value:any, type:string):void; 21class Foo { 22 x: string; 23} 24 25declare function getFooOrNull(): Foo | null; 26declare function getStringOrNumberOrNull(): string | number | null; 27 28function f1() { 29 let foo: Foo | null; 30AssertType(foo, "union"); 31AssertType(null, "null"); 32 33 if ((foo = getFooOrNull()) !== null) { 34AssertType((foo = getFooOrNull()) !== null, "boolean"); 35AssertType((foo = getFooOrNull()), "union"); 36AssertType(foo = getFooOrNull(), "union"); 37AssertType(foo, "union"); 38AssertType(getFooOrNull(), "union"); 39AssertType(getFooOrNull, "() => union"); 40AssertType(null, "null"); 41 42 foo; // Foo 43AssertType(foo, "Foo"); 44 } 45} 46 47function f2() { 48 let foo1: Foo | null; 49AssertType(foo1, "union"); 50AssertType(null, "null"); 51 52 let foo2: Foo | null; 53AssertType(foo2, "union"); 54AssertType(null, "null"); 55 56 if ((foo1 = getFooOrNull(), foo2 = foo1) !== null) { 57AssertType((foo1 = getFooOrNull(), foo2 = foo1) !== null, "boolean"); 58AssertType((foo1 = getFooOrNull(), foo2 = foo1), "union"); 59AssertType(foo1 = getFooOrNull(), foo2 = foo1, "union"); 60AssertType(foo1 = getFooOrNull(), "union"); 61AssertType(foo1, "union"); 62AssertType(getFooOrNull(), "union"); 63AssertType(getFooOrNull, "() => union"); 64AssertType(foo2 = foo1, "union"); 65AssertType(foo2, "union"); 66AssertType(foo1, "union"); 67AssertType(null, "null"); 68 69 foo1; // Foo | null 70AssertType(foo1, "union"); 71 72 foo2; // Foo 73AssertType(foo2, "Foo"); 74 } 75} 76 77function f3() { 78 let obj: Object | null; 79AssertType(obj, "union"); 80AssertType(null, "null"); 81 82 if ((obj = getFooOrNull()) instanceof Foo) { 83AssertType((obj = getFooOrNull()) instanceof Foo, "boolean"); 84AssertType((obj = getFooOrNull()), "union"); 85AssertType(obj = getFooOrNull(), "union"); 86AssertType(obj, "union"); 87AssertType(getFooOrNull(), "union"); 88AssertType(getFooOrNull, "() => union"); 89AssertType(Foo, "typeof Foo"); 90 91 obj; 92AssertType(obj, "Foo"); 93 } 94} 95 96function f4() { 97 let x: string | number | null; 98AssertType(x, "union"); 99AssertType(null, "null"); 100 101 if (typeof (x = getStringOrNumberOrNull()) === "number") { 102AssertType(typeof (x = getStringOrNumberOrNull()) === "number", "boolean"); 103AssertType(typeof (x = getStringOrNumberOrNull()), "union"); 104AssertType((x = getStringOrNumberOrNull()), "union"); 105AssertType(x = getStringOrNumberOrNull(), "union"); 106AssertType(x, "union"); 107AssertType(getStringOrNumberOrNull(), "union"); 108AssertType(getStringOrNumberOrNull, "() => union"); 109AssertType("number", "string"); 110 111 x; 112AssertType(x, "number"); 113 } 114} 115 116// Repro from #8851 117 118const re = /./g 119AssertType(re, "RegExp"); 120AssertType(/./g, "RegExp"); 121 122let match: RegExpExecArray | null 123AssertType(match, "union"); 124AssertType(null, "null"); 125 126while ((match = re.exec("xxx")) != null) { 127 const length = match[1].length + match[2].length 128AssertType(length, "number"); 129AssertType(match[1].length + match[2].length, "number"); 130AssertType(match[1].length, "number"); 131AssertType(match[1], "string"); 132AssertType(match, "RegExpExecArray"); 133AssertType(1, "int"); 134AssertType(match[2].length, "number"); 135AssertType(match[2], "string"); 136AssertType(match, "RegExpExecArray"); 137AssertType(2, "int"); 138} 139 140