• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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