• 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/compiler/narrowingByTypeofInSwitch.ts ===
20declare function AssertType(value:any, type:string):void;
21function assertNever(x: never) {
22AssertType(x, "never");
23    return x;
24}
25
26function assertNumber(x: number) {
27AssertType(x, "number");
28    return x;
29}
30
31function assertBoolean(x: boolean) {
32AssertType(x, "boolean");
33    return x;
34}
35
36function assertString(x: string) {
37AssertType(x, "string");
38    return x;
39}
40
41function assertSymbol(x: symbol) {
42AssertType(x, "symbol");
43    return x;
44}
45
46function assertFunction(x: Function) {
47AssertType(x, "Function");
48    return x;
49}
50
51function assertObject(x: object) {
52AssertType(x, "object");
53    return x;
54}
55
56function assertObjectOrNull(x: object | null) {
57AssertType(x, "union");
58    return x;
59}
60
61function assertUndefined(x: undefined) {
62AssertType(x, "undefined");
63    return x;
64}
65
66function assertAll(x: Basic) {
67AssertType(x, "Basic");
68    return x;
69}
70
71function assertStringOrNumber(x: string | number) {
72AssertType(x, "union");
73    return x;
74}
75
76function assertBooleanOrObject(x: boolean | object) {
77AssertType(x, "union");
78    return x;
79}
80
81type Basic = number | boolean | string | symbol | object | Function | undefined;
82
83function testUnion(x: Basic) {
84    switch (typeof x) {
85AssertType(typeof x, "union");
86AssertType(x, "Basic");
87
88        case 'number': assertNumber(x);
89AssertType('number', "string");
90AssertType(assertNumber(x), "number");
91AssertType(assertNumber, "(number) => number");
92AssertType(x, "number");
93return;
94
95        case 'boolean': assertBoolean(x);
96AssertType('boolean', "string");
97AssertType(assertBoolean(x), "boolean");
98AssertType(assertBoolean, "(boolean) => boolean");
99AssertType(x, "boolean");
100return;
101
102        case 'function': assertFunction(x);
103AssertType('function', "string");
104AssertType(assertFunction(x), "Function");
105AssertType(assertFunction, "(Function) => Function");
106AssertType(x, "Function");
107return;
108
109        case 'symbol': assertSymbol(x);
110AssertType('symbol', "string");
111AssertType(assertSymbol(x), "symbol");
112AssertType(assertSymbol, "(symbol) => symbol");
113AssertType(x, "symbol");
114return;
115
116        case 'object': assertObject(x);
117AssertType('object', "string");
118AssertType(assertObject(x), "object");
119AssertType(assertObject, "(object) => object");
120AssertType(x, "object");
121return;
122
123        case 'string': assertString(x);
124AssertType('string', "string");
125AssertType(assertString(x), "string");
126AssertType(assertString, "(string) => string");
127AssertType(x, "string");
128return;
129
130        case 'undefined': assertUndefined(x);
131AssertType('undefined', "string");
132AssertType(assertUndefined(x), "undefined");
133AssertType(assertUndefined, "(undefined) => undefined");
134AssertType(x, "undefined");
135return;
136    }
137    assertNever(x);
138AssertType(assertNever(x), "never");
139AssertType(assertNever, "(never) => never");
140AssertType(x, "never");
141}
142
143function testExtendsUnion<T extends Basic>(x: T) {
144    switch (typeof x) {
145AssertType(typeof x, "union");
146AssertType(x, "T");
147
148        case 'number': assertNumber(x);
149AssertType('number', "string");
150AssertType(assertNumber(x), "number");
151AssertType(assertNumber, "(number) => number");
152AssertType(x, "number");
153return;
154
155        case 'boolean': assertBoolean(x);
156AssertType('boolean', "string");
157AssertType(assertBoolean(x), "boolean");
158AssertType(assertBoolean, "(boolean) => boolean");
159AssertType(x, "boolean");
160return;
161
162        case 'function': assertAll(x);
163AssertType('function', "string");
164AssertType(assertAll(x), "Basic");
165AssertType(assertAll, "(Basic) => Basic");
166AssertType(x, "Function");
167return;
168
169        case 'symbol': assertSymbol(x);
170AssertType('symbol', "string");
171AssertType(assertSymbol(x), "symbol");
172AssertType(assertSymbol, "(symbol) => symbol");
173AssertType(x, "symbol");
174return;
175
176        case 'object': assertAll(x);
177AssertType('object', "string");
178AssertType(assertAll(x), "Basic");
179AssertType(assertAll, "(Basic) => Basic");
180AssertType(x, "object");
181return;
182
183        case 'string': assertString(x);
184AssertType('string', "string");
185AssertType(assertString(x), "string");
186AssertType(assertString, "(string) => string");
187AssertType(x, "string");
188return;
189
190        case 'undefined': assertUndefined(x);
191AssertType('undefined', "string");
192AssertType(assertUndefined(x), "undefined");
193AssertType(assertUndefined, "(undefined) => undefined");
194AssertType(x, "undefined");
195return;
196    }
197    assertAll(x);
198AssertType(assertAll(x), "Basic");
199AssertType(assertAll, "(Basic) => Basic");
200AssertType(x, "never");
201}
202
203function testAny(x: any) {
204    switch (typeof x) {
205AssertType(typeof x, "union");
206AssertType(x, "any");
207
208        case 'number': assertNumber(x);
209AssertType('number', "string");
210AssertType(assertNumber(x), "number");
211AssertType(assertNumber, "(number) => number");
212AssertType(x, "number");
213return;
214
215        case 'boolean': assertBoolean(x);
216AssertType('boolean', "string");
217AssertType(assertBoolean(x), "boolean");
218AssertType(assertBoolean, "(boolean) => boolean");
219AssertType(x, "boolean");
220return;
221
222        case 'function': assertFunction(x);
223AssertType('function', "string");
224AssertType(assertFunction(x), "Function");
225AssertType(assertFunction, "(Function) => Function");
226AssertType(x, "any");
227return;
228
229        case 'symbol': assertSymbol(x);
230AssertType('symbol', "string");
231AssertType(assertSymbol(x), "symbol");
232AssertType(assertSymbol, "(symbol) => symbol");
233AssertType(x, "symbol");
234return;
235
236        case 'object': assertObject(x);
237AssertType('object', "string");
238AssertType(assertObject(x), "object");
239AssertType(assertObject, "(object) => object");
240AssertType(x, "any");
241return;
242
243        case 'string': assertString(x);
244AssertType('string', "string");
245AssertType(assertString(x), "string");
246AssertType(assertString, "(string) => string");
247AssertType(x, "string");
248return;
249
250        case 'undefined': assertUndefined(x);
251AssertType('undefined', "string");
252AssertType(assertUndefined(x), "undefined");
253AssertType(assertUndefined, "(undefined) => undefined");
254AssertType(x, "undefined");
255return;
256    }
257    assertAll(x); // is any
258AssertType(assertAll(x), "Basic");
259AssertType(assertAll, "(Basic) => Basic");
260AssertType(x, "any");
261}
262
263function a1(x: string | object | undefined) {
264AssertType(x, "union");
265    return x;
266}
267
268function testUnionExplicitDefault(x: Basic) {
269    switch (typeof x) {
270AssertType(typeof x, "union");
271AssertType(x, "Basic");
272
273        case 'number': assertNumber(x);
274AssertType('number', "string");
275AssertType(assertNumber(x), "number");
276AssertType(assertNumber, "(number) => number");
277AssertType(x, "number");
278return;
279
280        case 'boolean': assertBoolean(x);
281AssertType('boolean', "string");
282AssertType(assertBoolean(x), "boolean");
283AssertType(assertBoolean, "(boolean) => boolean");
284AssertType(x, "boolean");
285return;
286
287        case 'function': assertFunction(x);
288AssertType('function', "string");
289AssertType(assertFunction(x), "Function");
290AssertType(assertFunction, "(Function) => Function");
291AssertType(x, "Function");
292return;
293
294        case 'symbol': assertSymbol(x);
295AssertType('symbol', "string");
296AssertType(assertSymbol(x), "symbol");
297AssertType(assertSymbol, "(symbol) => symbol");
298AssertType(x, "symbol");
299return;
300
301        default: a1(x);
302AssertType(a1(x), "union");
303AssertType(a1, "(union) => union");
304AssertType(x, "union");
305return;
306    }
307}
308
309function testUnionImplicitDefault(x: Basic) {
310    switch (typeof x) {
311AssertType(typeof x, "union");
312AssertType(x, "Basic");
313
314        case 'number': assertNumber(x);
315AssertType('number', "string");
316AssertType(assertNumber(x), "number");
317AssertType(assertNumber, "(number) => number");
318AssertType(x, "number");
319return;
320
321        case 'boolean': assertBoolean(x);
322AssertType('boolean', "string");
323AssertType(assertBoolean(x), "boolean");
324AssertType(assertBoolean, "(boolean) => boolean");
325AssertType(x, "boolean");
326return;
327
328        case 'function': assertFunction(x);
329AssertType('function', "string");
330AssertType(assertFunction(x), "Function");
331AssertType(assertFunction, "(Function) => Function");
332AssertType(x, "Function");
333return;
334
335        case 'symbol': assertSymbol(x);
336AssertType('symbol', "string");
337AssertType(assertSymbol(x), "symbol");
338AssertType(assertSymbol, "(symbol) => symbol");
339AssertType(x, "symbol");
340return;
341    }
342AssertType(a1(x), "union");
343AssertType(a1, "(union) => union");
344AssertType(x, "union");
345    return a1(x);
346}
347
348function testExtendsExplicitDefault<T extends Basic>(x: T) {
349    switch (typeof x) {
350AssertType(typeof x, "union");
351AssertType(x, "T");
352
353        case 'number': assertNumber(x);
354AssertType('number', "string");
355AssertType(assertNumber(x), "number");
356AssertType(assertNumber, "(number) => number");
357AssertType(x, "number");
358return;
359
360        case 'boolean': assertBoolean(x);
361AssertType('boolean', "string");
362AssertType(assertBoolean(x), "boolean");
363AssertType(assertBoolean, "(boolean) => boolean");
364AssertType(x, "boolean");
365return;
366
367        case 'function': assertAll(x);
368AssertType('function', "string");
369AssertType(assertAll(x), "Basic");
370AssertType(assertAll, "(Basic) => Basic");
371AssertType(x, "Function");
372return;
373
374        case 'symbol': assertSymbol(x);
375AssertType('symbol', "string");
376AssertType(assertSymbol(x), "symbol");
377AssertType(assertSymbol, "(symbol) => symbol");
378AssertType(x, "symbol");
379return;
380
381        default: assertAll(x);
382AssertType(assertAll(x), "Basic");
383AssertType(assertAll, "(Basic) => Basic");
384AssertType(x, "union");
385return;
386
387    }
388}
389
390function testExtendsImplicitDefault<T extends Basic>(x: T) {
391    switch (typeof x) {
392AssertType(typeof x, "union");
393AssertType(x, "T");
394
395        case 'number': assertNumber(x);
396AssertType('number', "string");
397AssertType(assertNumber(x), "number");
398AssertType(assertNumber, "(number) => number");
399AssertType(x, "number");
400return;
401
402        case 'boolean': assertBoolean(x);
403AssertType('boolean', "string");
404AssertType(assertBoolean(x), "boolean");
405AssertType(assertBoolean, "(boolean) => boolean");
406AssertType(x, "boolean");
407return;
408
409        case 'function': assertAll(x);
410AssertType('function', "string");
411AssertType(assertAll(x), "Basic");
412AssertType(assertAll, "(Basic) => Basic");
413AssertType(x, "Function");
414return;
415
416        case 'symbol': assertSymbol(x);
417AssertType('symbol', "string");
418AssertType(assertSymbol(x), "symbol");
419AssertType(assertSymbol, "(symbol) => symbol");
420AssertType(x, "symbol");
421return;
422    }
423AssertType(assertAll(x), "Basic");
424AssertType(assertAll, "(Basic) => Basic");
425AssertType(x, "union");
426    return assertAll(x);
427}
428
429type L = (x: number) => string;
430type R = { x: string, y: number }
431
432function exhaustiveChecks(x: number | string | L | R): string {
433    switch (typeof x) {
434AssertType(typeof x, "union");
435AssertType(x, "union");
436
437        case 'number':
438AssertType('number', "string");
439AssertType(x.toString(2), "string");
440AssertType(x.toString, "(?union) => string");
441AssertType(2, "int");
442return x.toString(2);
443
444        case 'string':
445AssertType('string', "string");
446AssertType(x, "string");
447return x;
448
449        case 'function':
450AssertType('function', "string");
451AssertType(x(42), "string");
452AssertType(x, "L");
453AssertType(42, "int");
454return x(42);
455
456        case 'object':
457AssertType('object', "string");
458AssertType(x.x, "string");
459return x.x;
460    }
461}
462
463function exhaustiveChecksGenerics<T extends L | R | number | string>(x: T): string {
464    switch (typeof x) {
465AssertType(typeof x, "union");
466AssertType(x, "T");
467
468        case 'number':
469AssertType('number', "string");
470AssertType(x.toString(2), "string");
471AssertType(x.toString, "(?union) => string");
472AssertType(2, "int");
473return x.toString(2);
474
475        case 'string':
476AssertType('string', "string");
477AssertType(x, "string");
478return x;
479
480        case 'function':
481AssertType('function', "string");
482AssertType((x as L)(42), "string");
483AssertType((x as L), "L");
484AssertType(x as L, "L");
485AssertType(x, "L");
486AssertType(42, "int");
487return (x as L)(42); // Can't narrow generic
488
489        case 'object':
490AssertType('object', "string");
491AssertType((x as R).x, "string");
492AssertType((x as R), "R");
493AssertType(x as R, "R");
494AssertType(x, "R");
495return (x as R).x;            // Can't narrow generic
496    }
497}
498
499function multipleGeneric<X extends L, Y extends R>(xy: X | Y): [X, string] | [Y, number] {
500    switch (typeof xy) {
501AssertType(typeof xy, "union");
502AssertType(xy, "union");
503
504        case 'function':
505AssertType('function', "string");
506AssertType([xy, xy(42)], "[X, string]");
507AssertType(xy, "X");
508AssertType(xy(42), "string");
509AssertType(xy, "X");
510AssertType(42, "int");
511return [xy, xy(42)];
512
513        case 'object':
514AssertType('object', "string");
515AssertType([xy, xy.y], "[Y, number]");
516AssertType(xy, "Y");
517AssertType(xy.y, "number");
518return [xy, xy.y];
519
520        default:
521AssertType(assertNever(xy), "never");
522AssertType(assertNever, "(never) => never");
523AssertType(xy, "never");
524return assertNever(xy);
525    }
526}
527
528function multipleGenericFuse<X extends L | number, Y extends R | number>(xy: X | Y): [X, number] | [Y, string] | [(X | Y)] {
529    switch (typeof xy) {
530AssertType(typeof xy, "union");
531AssertType(xy, "union");
532
533        case 'function':
534AssertType('function', "string");
535AssertType([xy, 1], "[X & Function, 1]");
536AssertType(xy, "X & Function");
537AssertType(1, "int");
538return [xy, 1];
539
540        case 'object':
541AssertType('object', "string");
542AssertType([xy, 'two'], "[Y & object, string]");
543AssertType(xy, "Y & object");
544AssertType('two', "string");
545return [xy, 'two'];
546
547        case 'number':
548AssertType('number', "string");
549AssertType([xy], "[union]");
550AssertType(xy, "union");
551return [xy]
552    }
553}
554
555function multipleGenericExhaustive<X extends L, Y extends R>(xy: X | Y): [X, string] | [Y, number] {
556    switch (typeof xy) {
557AssertType(typeof xy, "union");
558AssertType(xy, "union");
559
560        case 'object':
561AssertType('object', "string");
562AssertType([xy, xy.y], "[Y, number]");
563AssertType(xy, "Y");
564AssertType(xy.y, "number");
565return [xy, xy.y];
566
567        case 'function':
568AssertType('function', "string");
569AssertType([xy, xy(42)], "[X, string]");
570AssertType(xy, "X");
571AssertType(xy(42), "string");
572AssertType(xy, "X");
573AssertType(42, "int");
574return [xy, xy(42)];
575    }
576}
577
578function switchOrdering(x: string | number | boolean) {
579    switch (typeof x) {
580AssertType(typeof x, "union");
581AssertType(x, "union");
582
583        case 'string':
584AssertType('string', "string");
585AssertType(assertString(x), "string");
586AssertType(assertString, "(string) => string");
587AssertType(x, "string");
588return assertString(x);
589
590        case 'number':
591AssertType('number', "string");
592AssertType(assertNumber(x), "number");
593AssertType(assertNumber, "(number) => number");
594AssertType(x, "number");
595return assertNumber(x);
596
597        case 'boolean':
598AssertType('boolean', "string");
599AssertType(assertBoolean(x), "boolean");
600AssertType(assertBoolean, "(boolean) => boolean");
601AssertType(x, "boolean");
602return assertBoolean(x);
603
604        case 'number':
605AssertType('number', "string");
606AssertType(assertNever(x), "never");
607AssertType(assertNever, "(never) => never");
608AssertType(x, "never");
609return assertNever(x);
610    }
611}
612
613function switchOrderingWithDefault(x: string | number | boolean) {
614    function local(y: string | number | boolean) {
615AssertType(local, "(union) => union");
616AssertType(y, "union");
617
618AssertType(x, "union");
619        return x;
620    }
621    switch (typeof x) {
622AssertType(typeof x, "union");
623AssertType(x, "union");
624
625        case 'string':
626AssertType('string', "string");
627
628        case 'number':
629AssertType('number', "string");
630
631        default:
632AssertType(local(x), "union");
633AssertType(local, "(union) => union");
634AssertType(x, "union");
635return local(x)
636
637        case 'string':
638AssertType('string', "string");
639AssertType(assertNever(x), "never");
640AssertType(assertNever, "(never) => never");
641AssertType(x, "never");
642return assertNever(x);
643
644        case 'number':
645AssertType('number', "string");
646AssertType(assertNever(x), "never");
647AssertType(assertNever, "(never) => never");
648AssertType(x, "never");
649return assertNever(x);
650    }
651}
652
653function fallThroughTest(x: string | number | boolean | object) {
654    switch (typeof x) {
655AssertType(typeof x, "union");
656AssertType(x, "union");
657
658        case 'number':
659AssertType('number', "string");
660
661            assertNumber(x)
662AssertType(assertNumber(x), "number");
663AssertType(assertNumber, "(number) => number");
664AssertType(x, "number");
665
666        case 'string':
667AssertType('string', "string");
668
669            assertStringOrNumber(x)
670AssertType(assertStringOrNumber(x), "union");
671AssertType(assertStringOrNumber, "(union) => union");
672AssertType(x, "union");
673
674            break;
675        default:
676            assertObject(x);
677AssertType(assertObject(x), "object");
678AssertType(assertObject, "(object) => object");
679AssertType(x, "object");
680
681        case 'number':
682AssertType('number', "string");
683
684        case 'boolean':
685AssertType('boolean', "string");
686
687            assertBooleanOrObject(x);
688AssertType(assertBooleanOrObject(x), "union");
689AssertType(assertBooleanOrObject, "(union) => union");
690AssertType(x, "union");
691
692            break;
693    }
694}
695
696function unknownNarrowing(x: unknown) {
697    switch (typeof x) {
698AssertType(typeof x, "union");
699AssertType(x, "unknown");
700
701        case 'number': assertNumber(x);
702AssertType('number', "string");
703AssertType(assertNumber(x), "number");
704AssertType(assertNumber, "(number) => number");
705AssertType(x, "number");
706return;
707
708        case 'boolean': assertBoolean(x);
709AssertType('boolean', "string");
710AssertType(assertBoolean(x), "boolean");
711AssertType(assertBoolean, "(boolean) => boolean");
712AssertType(x, "boolean");
713return;
714
715        case 'function': assertFunction(x);
716AssertType('function', "string");
717AssertType(assertFunction(x), "Function");
718AssertType(assertFunction, "(Function) => Function");
719AssertType(x, "Function");
720return;
721
722        case 'symbol': assertSymbol(x);
723AssertType('symbol', "string");
724AssertType(assertSymbol(x), "symbol");
725AssertType(assertSymbol, "(symbol) => symbol");
726AssertType(x, "symbol");
727return;
728
729        case 'object': assertObjectOrNull(x);
730AssertType('object', "string");
731AssertType(assertObjectOrNull(x), "union");
732AssertType(assertObjectOrNull, "(union) => union");
733AssertType(x, "union");
734return;
735
736        case 'string': assertString(x);
737AssertType('string', "string");
738AssertType(assertString(x), "string");
739AssertType(assertString, "(string) => string");
740AssertType(x, "string");
741return;
742
743        case 'undefined': assertUndefined(x);
744AssertType('undefined', "string");
745AssertType(assertUndefined(x), "undefined");
746AssertType(assertUndefined, "(undefined) => undefined");
747AssertType(x, "undefined");
748return;
749    }
750}
751
752function keyofNarrowing<S extends { [K in keyof S]: string }>(k: keyof S) {
753    function assertKeyofS(k1: keyof S) {
754AssertType(assertKeyofS, "(keyof S) => void");
755
756AssertType(k1, "keyof S");
757}
758
759    switch (typeof k) {
760AssertType(typeof k, "union");
761AssertType(k, "keyof S");
762
763        case 'number': assertNumber(k); assertKeyofS(k);
764AssertType('number', "string");
765AssertType(assertNumber(k), "number");
766AssertType(assertNumber, "(number) => number");
767AssertType(k, "number");
768AssertType(assertKeyofS(k), "void");
769AssertType(assertKeyofS, "(keyof S) => void");
770AssertType(k, "keyof S & number");
771return;
772
773        case 'symbol': assertSymbol(k); assertKeyofS(k);
774AssertType('symbol', "string");
775AssertType(assertSymbol(k), "symbol");
776AssertType(assertSymbol, "(symbol) => symbol");
777AssertType(k, "symbol");
778AssertType(assertKeyofS(k), "void");
779AssertType(assertKeyofS, "(keyof S) => void");
780AssertType(k, "keyof S & symbol");
781return;
782
783        case 'string': assertString(k); assertKeyofS(k);
784AssertType('string', "string");
785AssertType(assertString(k), "string");
786AssertType(assertString, "(string) => string");
787AssertType(k, "string");
788AssertType(assertKeyofS(k), "void");
789AssertType(assertKeyofS, "(keyof S) => void");
790AssertType(k, "keyof S & string");
791return;
792    }
793}
794
795function narrowingNarrows(x: {} | undefined) {
796    switch (typeof x) {
797AssertType(typeof x, "union");
798AssertType(x, "union");
799
800        case 'number': assertNumber(x);
801AssertType('number', "string");
802AssertType(assertNumber(x), "number");
803AssertType(assertNumber, "(number) => number");
804AssertType(x, "number");
805return;
806
807        case 'boolean': assertBoolean(x);
808AssertType('boolean', "string");
809AssertType(assertBoolean(x), "boolean");
810AssertType(assertBoolean, "(boolean) => boolean");
811AssertType(x, "boolean");
812return;
813
814        case 'function': assertFunction(x);
815AssertType('function', "string");
816AssertType(assertFunction(x), "Function");
817AssertType(assertFunction, "(Function) => Function");
818AssertType(x, "Function");
819return;
820
821        case 'symbol': assertSymbol(x);
822AssertType('symbol', "string");
823AssertType(assertSymbol(x), "symbol");
824AssertType(assertSymbol, "(symbol) => symbol");
825AssertType(x, "symbol");
826return;
827
828        case 'object': const _: {} = x;
829AssertType('object', "string");
830AssertType(_, "{}");
831AssertType(x, "object");
832return;
833
834        case 'string': assertString(x);
835AssertType('string', "string");
836AssertType(assertString(x), "string");
837AssertType(assertString, "(string) => string");
838AssertType(x, "string");
839return;
840
841        case 'undefined': assertUndefined(x);
842AssertType('undefined', "string");
843AssertType(assertUndefined(x), "undefined");
844AssertType(assertUndefined, "(undefined) => undefined");
845AssertType(x, "undefined");
846return;
847
848        case 'number': assertNever(x);
849AssertType('number', "string");
850AssertType(assertNever(x), "never");
851AssertType(assertNever, "(never) => never");
852AssertType(x, "never");
853return;
854
855        default: const _y: {} = x;
856AssertType(_y, "{}");
857AssertType(x, "{}");
858return;
859    }
860}
861
862function narrowingNarrows2(x: true | 3 | 'hello' | undefined) {
863    switch (typeof x) {
864AssertType(typeof x, "union");
865AssertType(x, "union");
866
867        case 'number': assertNumber(x);
868AssertType('number', "string");
869AssertType(assertNumber(x), "number");
870AssertType(assertNumber, "(number) => number");
871AssertType(x, "int");
872return;
873
874        case 'boolean': assertBoolean(x);
875AssertType('boolean', "string");
876AssertType(assertBoolean(x), "boolean");
877AssertType(assertBoolean, "(boolean) => boolean");
878AssertType(x, "boolean");
879return;
880
881        case 'function': assertNever(x);
882AssertType('function', "string");
883AssertType(assertNever(x), "never");
884AssertType(assertNever, "(never) => never");
885AssertType(x, "never");
886return;
887
888        case 'symbol': assertNever(x);
889AssertType('symbol', "string");
890AssertType(assertNever(x), "never");
891AssertType(assertNever, "(never) => never");
892AssertType(x, "never");
893return;
894
895        case 'object': const _: {} = assertNever(x);
896AssertType('object', "string");
897AssertType(_, "{}");
898AssertType(assertNever(x), "never");
899AssertType(assertNever, "(never) => never");
900AssertType(x, "never");
901return;
902
903        case 'string': assertString(x);
904AssertType('string', "string");
905AssertType(assertString(x), "string");
906AssertType(assertString, "(string) => string");
907AssertType(x, "string");
908return;
909
910        case 'undefined': assertUndefined(x);
911AssertType('undefined', "string");
912AssertType(assertUndefined(x), "undefined");
913AssertType(assertUndefined, "(undefined) => undefined");
914AssertType(x, "undefined");
915return;
916
917        case 'number': assertNever(x);
918AssertType('number', "string");
919AssertType(assertNever(x), "never");
920AssertType(assertNever, "(never) => never");
921AssertType(x, "never");
922return;
923
924        default: const _y: {} = assertNever(x);
925AssertType(_y, "{}");
926AssertType(assertNever(x), "never");
927AssertType(assertNever, "(never) => never");
928AssertType(x, "never");
929return;
930    }
931}
932
933/* Template literals */
934
935function testUnionWithTempalte(x: Basic) {
936    switch (typeof x) {
937AssertType(typeof x, "union");
938AssertType(x, "Basic");
939
940        case `number`: assertNumber(x);
941AssertType(`number`, "string");
942AssertType(assertNumber(x), "number");
943AssertType(assertNumber, "(number) => number");
944AssertType(x, "number");
945return;
946
947        case `boolean`: assertBoolean(x);
948AssertType(`boolean`, "string");
949AssertType(assertBoolean(x), "boolean");
950AssertType(assertBoolean, "(boolean) => boolean");
951AssertType(x, "boolean");
952return;
953
954        case `function`: assertFunction(x);
955AssertType(`function`, "string");
956AssertType(assertFunction(x), "Function");
957AssertType(assertFunction, "(Function) => Function");
958AssertType(x, "Function");
959return;
960
961        case `symbol`: assertSymbol(x);
962AssertType(`symbol`, "string");
963AssertType(assertSymbol(x), "symbol");
964AssertType(assertSymbol, "(symbol) => symbol");
965AssertType(x, "symbol");
966return;
967
968        case `object`: assertObject(x);
969AssertType(`object`, "string");
970AssertType(assertObject(x), "object");
971AssertType(assertObject, "(object) => object");
972AssertType(x, "object");
973return;
974
975        case `string`: assertString(x);
976AssertType(`string`, "string");
977AssertType(assertString(x), "string");
978AssertType(assertString, "(string) => string");
979AssertType(x, "string");
980return;
981
982        case `undefined`: assertUndefined(x);
983AssertType(`undefined`, "string");
984AssertType(assertUndefined(x), "undefined");
985AssertType(assertUndefined, "(undefined) => undefined");
986AssertType(x, "undefined");
987return;
988    }
989    assertNever(x);
990AssertType(assertNever(x), "never");
991AssertType(assertNever, "(never) => never");
992AssertType(x, "never");
993}
994
995function fallThroughTestWithTempalte(x: string | number | boolean | object) {
996    switch (typeof x) {
997AssertType(typeof x, "union");
998AssertType(x, "union");
999
1000        case `number`:
1001AssertType(`number`, "string");
1002
1003            assertNumber(x)
1004AssertType(assertNumber(x), "number");
1005AssertType(assertNumber, "(number) => number");
1006AssertType(x, "number");
1007
1008        case `string`:
1009AssertType(`string`, "string");
1010
1011            assertStringOrNumber(x)
1012AssertType(assertStringOrNumber(x), "union");
1013AssertType(assertStringOrNumber, "(union) => union");
1014AssertType(x, "union");
1015
1016            break;
1017        default:
1018            assertObject(x);
1019AssertType(assertObject(x), "object");
1020AssertType(assertObject, "(object) => object");
1021AssertType(x, "object");
1022
1023        case `number`:
1024AssertType(`number`, "string");
1025
1026        case `boolean`:
1027AssertType(`boolean`, "string");
1028
1029            assertBooleanOrObject(x);
1030AssertType(assertBooleanOrObject(x), "union");
1031AssertType(assertBooleanOrObject, "(union) => union");
1032AssertType(x, "union");
1033
1034            break;
1035    }
1036}
1037
1038function keyofNarrowingWithTemplate<S extends { [K in keyof S]: string }>(k: keyof S) {
1039    function assertKeyofS(k1: keyof S) {
1040AssertType(assertKeyofS, "(keyof S) => void");
1041
1042AssertType(k1, "keyof S");
1043}
1044
1045    switch (typeof k) {
1046AssertType(typeof k, "union");
1047AssertType(k, "keyof S");
1048
1049        case `number`: assertNumber(k); assertKeyofS(k);
1050AssertType(`number`, "string");
1051AssertType(assertNumber(k), "number");
1052AssertType(assertNumber, "(number) => number");
1053AssertType(k, "number");
1054AssertType(assertKeyofS(k), "void");
1055AssertType(assertKeyofS, "(keyof S) => void");
1056AssertType(k, "keyof S & number");
1057return;
1058
1059        case `symbol`: assertSymbol(k); assertKeyofS(k);
1060AssertType(`symbol`, "string");
1061AssertType(assertSymbol(k), "symbol");
1062AssertType(assertSymbol, "(symbol) => symbol");
1063AssertType(k, "symbol");
1064AssertType(assertKeyofS(k), "void");
1065AssertType(assertKeyofS, "(keyof S) => void");
1066AssertType(k, "keyof S & symbol");
1067return;
1068
1069        case `string`: assertString(k); assertKeyofS(k);
1070AssertType(`string`, "string");
1071AssertType(assertString(k), "string");
1072AssertType(assertString, "(string) => string");
1073AssertType(k, "string");
1074AssertType(assertKeyofS(k), "void");
1075AssertType(assertKeyofS, "(keyof S) => void");
1076AssertType(k, "keyof S & string");
1077return;
1078    }
1079}
1080
1081/* Both string literals and template literals */
1082
1083function multipleGenericFuseWithBoth<X extends L | number, Y extends R | number>(xy: X | Y): [X, number] | [Y, string] | [(X | Y)] {
1084    switch (typeof xy) {
1085AssertType(typeof xy, "union");
1086AssertType(xy, "union");
1087
1088        case `function`:
1089AssertType(`function`, "string");
1090AssertType([xy, 1], "[X & Function, 1]");
1091AssertType(xy, "X & Function");
1092AssertType(1, "int");
1093return [xy, 1];
1094
1095        case 'object':
1096AssertType('object', "string");
1097AssertType([xy, 'two'], "[Y & object, string]");
1098AssertType(xy, "Y & object");
1099AssertType('two', "string");
1100return [xy, 'two'];
1101
1102        case `number`:
1103AssertType(`number`, "string");
1104AssertType([xy], "[union]");
1105AssertType(xy, "union");
1106return [xy]
1107    }
1108}
1109
1110
1111