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/typeGuardsAsAssertions.ts === 20declare function AssertType(value:any, type:string):void; 21// Repro from #8513 22 23let cond: boolean; 24AssertType(cond, "boolean"); 25 26export type Optional<a> = Some<a> | None; 27 28export interface None { readonly none: string; } 29export interface Some<a> { readonly some: a; } 30 31export const none : None = { none: '' }; 32AssertType(none, "None"); 33AssertType({ none: '' }, "{ none: string; }"); 34AssertType(none, "string"); 35AssertType('', "string"); 36 37export function isSome<a>(value: Optional<a>): value is Some<a> { 38AssertType('some' in value, "boolean"); 39AssertType('some', "string"); 40AssertType(value, "Optional<a>"); 41 return 'some' in value; 42} 43 44function someFrom<a>(some: a) { 45AssertType({ some }, "{ some: a; }"); 46AssertType(some, "a"); 47 return { some }; 48} 49 50export function fn<r>(makeSome: () => r): void { 51 let result: Optional<r> = none; 52AssertType(result, "Optional<r>"); 53AssertType(none, "None"); 54 55 result; // None 56AssertType(result, "None"); 57 58 while (cond) { 59AssertType(cond, "boolean"); 60 61 result; // Some<r> | None 62AssertType(result, "Optional<r>"); 63 64 result = someFrom(isSome(result) ? result.some : makeSome()); 65AssertType(result = someFrom(isSome(result) ? result.some : makeSome()), "{ some: r; }"); 66AssertType(result, "Optional<r>"); 67AssertType(someFrom(isSome(result) ? result.some : makeSome()), "{ some: r; }"); 68AssertType(someFrom, "<a>(a) => { some: a; }"); 69AssertType(isSome(result) ? result.some : makeSome(), "r"); 70AssertType(isSome(result), "boolean"); 71AssertType(isSome, "<a>(Optional<a>) => value is Some<a>"); 72AssertType(result, "Optional<r>"); 73AssertType(result.some, "r"); 74AssertType(makeSome(), "r"); 75AssertType(makeSome, "() => r"); 76 77 result; // Some<r> 78AssertType(result, "Some<r>"); 79 } 80} 81 82function foo1() { 83 let x: string | number | boolean = 0; 84AssertType(x, "union"); 85AssertType(0, "int"); 86 87 x; // number 88AssertType(x, "number"); 89 90 while (cond) { 91AssertType(cond, "boolean"); 92 93 x; // number, then string | number 94AssertType(x, "union"); 95 96 x = typeof x === "string" ? x.slice() : "abc"; 97AssertType(x = typeof x === "string" ? x.slice() : "abc", "string"); 98AssertType(x, "union"); 99AssertType(typeof x === "string" ? x.slice() : "abc", "string"); 100AssertType(typeof x === "string", "boolean"); 101AssertType(typeof x, "union"); 102AssertType(x, "union"); 103AssertType("string", "string"); 104AssertType(x.slice(), "string"); 105AssertType(x.slice, "(?union, ?union) => string"); 106AssertType("abc", "string"); 107 108 x; // string 109AssertType(x, "string"); 110 } 111 x; 112AssertType(x, "union"); 113} 114 115function foo2() { 116 let x: string | number | boolean = 0; 117AssertType(x, "union"); 118AssertType(0, "int"); 119 120 x; // number 121AssertType(x, "number"); 122 123 while (cond) { 124AssertType(cond, "boolean"); 125 126 x; // number, then string | number 127AssertType(x, "union"); 128 129 if (typeof x === "string") { 130AssertType(typeof x === "string", "boolean"); 131AssertType(typeof x, "union"); 132AssertType(x, "union"); 133AssertType("string", "string"); 134 135 x = x.slice(); 136AssertType(x = x.slice(), "string"); 137AssertType(x, "union"); 138AssertType(x.slice(), "string"); 139AssertType(x.slice, "(?union, ?union) => string"); 140 } 141 else { 142 x = "abc"; 143AssertType(x = "abc", "string"); 144AssertType(x, "union"); 145AssertType("abc", "string"); 146 } 147 x; // string 148AssertType(x, "string"); 149 } 150 x; 151AssertType(x, "union"); 152} 153 154// Type guards as assertions 155 156function f1() { 157 let x: string | number | undefined = undefined; 158AssertType(x, "union"); 159AssertType(undefined, "undefined"); 160 161 x; // undefined 162AssertType(x, "undefined"); 163 164 if (x) { 165AssertType(x, "undefined"); 166 167 x; // string | number (guard as assertion) 168AssertType(x, "never"); 169 } 170 x; // string | number | undefined 171AssertType(x, "undefined"); 172} 173 174function f2() { 175 let x: string | number | undefined = undefined; 176AssertType(x, "union"); 177AssertType(undefined, "undefined"); 178 179 x; // undefined 180AssertType(x, "undefined"); 181 182 if (typeof x === "string") { 183AssertType(typeof x === "string", "boolean"); 184AssertType(typeof x, "union"); 185AssertType(x, "undefined"); 186AssertType("string", "string"); 187 188 x; // string (guard as assertion) 189AssertType(x, "never"); 190 } 191 x; // string | undefined 192AssertType(x, "undefined"); 193} 194 195function f3() { 196 let x: string | number | undefined = undefined; 197AssertType(x, "union"); 198AssertType(undefined, "undefined"); 199 200 x; // undefined 201AssertType(x, "undefined"); 202 203 if (!x) { 204AssertType(!x, "boolean"); 205AssertType(x, "undefined"); 206 207 return; 208 } 209 x; // string | number (guard as assertion) 210AssertType(x, "never"); 211} 212 213function f4() { 214 let x: string | number | undefined = undefined; 215AssertType(x, "union"); 216AssertType(undefined, "undefined"); 217 218 x; // undefined 219AssertType(x, "undefined"); 220 221 if (typeof x === "boolean") { 222AssertType(typeof x === "boolean", "boolean"); 223AssertType(typeof x, "union"); 224AssertType(x, "undefined"); 225AssertType("boolean", "string"); 226 227 x; // nothing (boolean not in declared type) 228AssertType(x, "never"); 229 } 230 x; // undefined 231AssertType(x, "undefined"); 232} 233 234function f5(x: string | number) { 235 if (typeof x === "string" && typeof x === "number") { 236AssertType(typeof x === "string" && typeof x === "number", "boolean"); 237AssertType(typeof x === "string", "boolean"); 238AssertType(typeof x, "union"); 239AssertType(x, "union"); 240AssertType("string", "string"); 241AssertType(typeof x === "number", "boolean"); 242AssertType(typeof x, "union"); 243AssertType(x, "string"); 244AssertType("number", "string"); 245 246 x; // number (guard as assertion) 247AssertType(x, "never"); 248 } 249 else { 250 x; // string | number 251AssertType(x, "union"); 252 } 253 x; // string | number 254AssertType(x, "union"); 255} 256 257function f6() { 258 let x: string | undefined | null; 259AssertType(x, "union"); 260AssertType(null, "null"); 261 262 x!.slice(); 263AssertType(x!.slice(), "string"); 264AssertType(x!.slice, "(?union, ?union) => string"); 265AssertType(x!, "string"); 266AssertType(x, "union"); 267 268 x = ""; 269AssertType(x = "", "string"); 270AssertType(x, "union"); 271AssertType("", "string"); 272 273 x!.slice(); 274AssertType(x!.slice(), "string"); 275AssertType(x!.slice, "(?union, ?union) => string"); 276AssertType(x!, "string"); 277AssertType(x, "string"); 278 279 x = undefined; 280AssertType(x = undefined, "undefined"); 281AssertType(x, "union"); 282AssertType(undefined, "undefined"); 283 284 x!.slice(); 285AssertType(x!.slice(), "string"); 286AssertType(x!.slice, "(?union, ?union) => string"); 287AssertType(x!, "string"); 288AssertType(x, "union"); 289 290 x = null; 291AssertType(x = null, "null"); 292AssertType(x, "union"); 293AssertType(null, "null"); 294 295 x!.slice(); 296AssertType(x!.slice(), "string"); 297AssertType(x!.slice, "(?union, ?union) => string"); 298AssertType(x!, "string"); 299AssertType(x, "union"); 300 301 x = <undefined | null>undefined; 302AssertType(x = <undefined | null>undefined, "union"); 303AssertType(x, "union"); 304AssertType(<undefined | null>undefined, "union"); 305AssertType(null, "null"); 306AssertType(undefined, "undefined"); 307 308 x!.slice(); 309AssertType(x!.slice(), "string"); 310AssertType(x!.slice, "(?union, ?union) => string"); 311AssertType(x!, "string"); 312AssertType(x, "union"); 313 314 x = <string | undefined>""; 315AssertType(x = <string | undefined>"", "union"); 316AssertType(x, "union"); 317AssertType(<string | undefined>"", "union"); 318AssertType("", "string"); 319 320 x!.slice(); 321AssertType(x!.slice(), "string"); 322AssertType(x!.slice, "(?union, ?union) => string"); 323AssertType(x!, "string"); 324AssertType(x, "union"); 325 326 x = <string | null>""; 327AssertType(x = <string | null>"", "union"); 328AssertType(x, "union"); 329AssertType(<string | null>"", "union"); 330AssertType(null, "null"); 331AssertType("", "string"); 332 333 x!.slice(); 334AssertType(x!.slice(), "string"); 335AssertType(x!.slice, "(?union, ?union) => string"); 336AssertType(x!, "string"); 337AssertType(x, "union"); 338} 339 340function f7() { 341 let x: string; 342AssertType(x, "string"); 343 344 x!.slice(); 345AssertType(x!.slice(), "string"); 346AssertType(x!.slice, "(?union, ?union) => string"); 347AssertType(x!, "string"); 348AssertType(x, "string"); 349} 350 351 352