• 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/expressions/typeGuards/typeGuardIntersectionTypes.ts ===
20declare function AssertType(value:any, type:string):void;
21interface X {
22    x: string;
23}
24
25interface Y {
26    y: string;
27}
28
29interface Z {
30    z: string;
31}
32
33declare function isX(obj: any): obj is X;
34declare function isY(obj: any): obj is Y;
35declare function isZ(obj: any): obj is Z;
36
37function f1(obj: Object) {
38    if (isX(obj) || isY(obj) || isZ(obj)) {
39AssertType(isX(obj) || isY(obj) || isZ(obj), "boolean");
40AssertType(isX(obj) || isY(obj), "boolean");
41AssertType(isX(obj), "boolean");
42AssertType(isX, "(any) => obj is X");
43AssertType(obj, "Object");
44AssertType(isY(obj), "boolean");
45AssertType(isY, "(any) => obj is Y");
46AssertType(obj, "Object");
47AssertType(isZ(obj), "boolean");
48AssertType(isZ, "(any) => obj is Z");
49AssertType(obj, "Object");
50
51        obj;
52AssertType(obj, "union");
53    }
54    if (isX(obj) && isY(obj) && isZ(obj)) {
55AssertType(isX(obj) && isY(obj) && isZ(obj), "boolean");
56AssertType(isX(obj) && isY(obj), "boolean");
57AssertType(isX(obj), "boolean");
58AssertType(isX, "(any) => obj is X");
59AssertType(obj, "Object");
60AssertType(isY(obj), "boolean");
61AssertType(isY, "(any) => obj is Y");
62AssertType(obj, "X");
63AssertType(isZ(obj), "boolean");
64AssertType(isZ, "(any) => obj is Z");
65AssertType(obj, "X & Y");
66
67        obj;
68AssertType(obj, "X & Y & Z");
69    }
70}
71
72// Repro from #8911
73
74// two interfaces
75interface A {
76  a: string;
77}
78
79interface B {
80  b: string;
81}
82
83// a type guard for B
84function isB(toTest: any): toTest is B {
85AssertType(toTest && toTest.b, "any");
86AssertType(toTest, "any");
87AssertType(toTest.b, "any");
88  return toTest && toTest.b;
89}
90
91// a function that turns an A into an A & B
92function union(a: A): A & B | null {
93  if (isB(a)) {
94AssertType(isB(a), "boolean");
95AssertType(isB, "(any) => toTest is B");
96AssertType(a, "A");
97
98AssertType(a, "A & B");
99    return a;
100
101  } else {
102AssertType(null, "null");
103    return null;
104  }
105}
106
107// Repro from #9016
108
109declare function log(s: string): void;
110
111// Supported beast features
112interface Beast     { wings?: boolean; legs?: number }
113interface Legged    { legs: number; }
114interface Winged    { wings: boolean; }
115
116// Beast feature detection via user-defined type guards
117function hasLegs(x: Beast): x is Legged {
118AssertType(x && typeof x.legs === 'number', "boolean");
119return x && typeof x.legs === 'number';
120
121AssertType(x, "Beast");
122
123AssertType(typeof x.legs === 'number', "boolean");
124
125AssertType(typeof x.legs, "union");
126
127AssertType(x.legs, "union");
128
129AssertType('number', "string");
130}
131
132function hasWings(x: Beast): x is Winged {
133AssertType(x && !!x.wings, "boolean");
134return x && !!x.wings;
135
136AssertType(x, "Beast");
137
138AssertType(!!x.wings, "boolean");
139
140AssertType(!x.wings, "boolean");
141
142AssertType(x.wings, "union");
143}
144
145// Function to identify a given beast by detecting its features
146function identifyBeast(beast: Beast) {
147
148    // All beasts with legs
149    if (hasLegs(beast)) {
150AssertType(hasLegs(beast), "boolean");
151AssertType(hasLegs, "(Beast) => x is Legged");
152AssertType(beast, "Beast");
153
154        // All winged beasts with legs
155        if (hasWings(beast)) {
156AssertType(hasWings(beast), "boolean");
157AssertType(hasWings, "(Beast) => x is Winged");
158AssertType(beast, "Legged");
159
160            if (beast.legs === 4) {
161AssertType(beast.legs === 4, "boolean");
162AssertType(beast.legs, "number");
163AssertType(4, "int");
164
165                log(`pegasus - 4 legs, wings`);
166AssertType(log(`pegasus - 4 legs, wings`), "void");
167AssertType(log, "(string) => void");
168AssertType(`pegasus - 4 legs, wings`, "string");
169            }
170            else if (beast.legs === 2) {
171AssertType(beast.legs === 2, "boolean");
172AssertType(beast.legs, "number");
173AssertType(2, "int");
174
175                log(`bird - 2 legs, wings`);
176AssertType(log(`bird - 2 legs, wings`), "void");
177AssertType(log, "(string) => void");
178AssertType(`bird - 2 legs, wings`, "string");
179            }
180            else {
181                log(`unknown - ${beast.legs} legs, wings`);
182AssertType(log(`unknown - ${beast.legs} legs, wings`), "void");
183AssertType(log, "(string) => void");
184AssertType(`unknown - ${beast.legs} legs, wings`, "string");
185AssertType(beast.legs, "number");
186            }
187        }
188
189        // All non-winged beasts with legs
190        else {
191            log(`manbearpig - ${beast.legs} legs, no wings`);
192AssertType(log(`manbearpig - ${beast.legs} legs, no wings`), "void");
193AssertType(log, "(string) => void");
194AssertType(`manbearpig - ${beast.legs} legs, no wings`, "string");
195AssertType(beast.legs, "number");
196        }
197    }
198
199    // All beasts without legs
200    else {
201        if (hasWings(beast)) {
202AssertType(hasWings(beast), "boolean");
203AssertType(hasWings, "(Beast) => x is Winged");
204AssertType(beast, "Beast");
205
206            log(`quetzalcoatl - no legs, wings`)
207AssertType(log(`quetzalcoatl - no legs, wings`), "void");
208AssertType(log, "(string) => void");
209AssertType(`quetzalcoatl - no legs, wings`, "string");
210        }
211        else {
212            log(`snake - no legs, no wings`)
213AssertType(log(`snake - no legs, no wings`), "void");
214AssertType(log, "(string) => void");
215AssertType(`snake - no legs, no wings`, "string");
216        }
217    }
218}
219
220function beastFoo(beast: Object) {
221    if (hasWings(beast) && hasLegs(beast)) {
222AssertType(hasWings(beast) && hasLegs(beast), "boolean");
223AssertType(hasWings(beast), "boolean");
224AssertType(hasWings, "(Beast) => x is Winged");
225AssertType(beast, "Object");
226AssertType(hasLegs(beast), "boolean");
227AssertType(hasLegs, "(Beast) => x is Legged");
228AssertType(beast, "Winged");
229
230        beast;  // Winged & Legged
231AssertType(beast, "Winged & Legged");
232    }
233    else {
234        beast;
235AssertType(beast, "Object");
236    }
237
238    if (hasLegs(beast) && hasWings(beast)) {
239AssertType(hasLegs(beast) && hasWings(beast), "boolean");
240AssertType(hasLegs(beast), "boolean");
241AssertType(hasLegs, "(Beast) => x is Legged");
242AssertType(beast, "Object");
243AssertType(hasWings(beast), "boolean");
244AssertType(hasWings, "(Beast) => x is Winged");
245AssertType(beast, "Legged");
246
247        beast;  // Legged & Winged
248AssertType(beast, "Legged & Winged");
249    }
250}
251
252