1..  Copyright (c) 2021-2024 Huawei Device Co., Ltd.
2    Licensed under the Apache License, Version 2.0 (the "License");
3    you may not use this file except in compliance with the License.
4    You may obtain a copy of the License at
5    http://www.apache.org/licenses/LICENSE-2.0
6    Unless required by applicable law or agreed to in writing, software
7    distributed under the License is distributed on an "AS IS" BASIS,
8    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9    See the License for the specific language governing permissions and
10    limitations under the License.
11
12Recipes
13=======
14
15.. _R001:
16
17|CB_R| #1: Objects with property names that are not identifiers are not supported
18---------------------------------------------------------------------------------
19
20|CB_RULE|
21~~~~~~~~~
22
23|LANG| does not support Objects with name properties that are numbers or
24strings. Use classes to access data by property names. Use arrays to access data
25by numeric indices.
26
27|CB_BAD|
28~~~~~~~~
29
30.. code-block:: typescript
31
32   var x = {"name": 1, 2: 3}
33
34   console.log(x["name"])
35   console.log(x[2])
36
37|CB_OK|
38~~~~~~~
39
40.. code-block:: typescript
41
42    class X {
43        public name: number
44    }
45    let x = {name: 1}
46    console.log(x.name)
47
48    let y = [1, 2, 3]
49    console.log(y[2])
50
51    // If you still need a container to store keys of different types,
52    // use Map<Object, some_type>:
53    let z = new Map<Object, number>()
54    z.set("name", 1)
55    z.set(2, 2)
56    console.log(z.get("name"))
57    console.log(z.get(2))
58
59|CB_SEE|
60~~~~~~~~
61
62* :ref:`R002`
63* :ref:`R052`
64* :ref:`R059`
65* :ref:`R060`
66* :ref:`R066`
67* :ref:`R105`
68* :ref:`R109`
69
70.. _R002:
71
72|CB_R| #2: ``Symbol()`` API is not supported
73--------------------------------------------
74
75|CB_RULE|
76~~~~~~~~~
77
78|LANG| does not support ``Symbol()`` API.
79
80|CB_BAD|
81~~~~~~~~
82
83|TS| has ``Symbol()`` API, which can be used among other things to generate
84unique property names at runtime:
85
86.. code-block:: typescript
87
88    const sym = Symbol()
89    let o = {
90       [sym]: "value"
91    }
92
93|CB_OK|
94~~~~~~~
95
96|LANG| does not support ``Symbol()`` API because its most popular use cases
97make no sense in the statically typed environment. In particular, the object
98layout is defined at compile time and cannot be changed at runtime.
99
100|CB_SEE|
101~~~~~~~~
102
103* :ref:`R001`
104* :ref:`R052`
105* :ref:`R059`
106* :ref:`R060`
107* :ref:`R066`
108* :ref:`R105`
109* :ref:`R109`
110
111.. _R003:
112
113|CB_R| #3: Private '#' identifiers are not supported
114----------------------------------------------------
115
116|CB_RULE|
117~~~~~~~~~
118
119|LANG| does not private identifiers started with ``#`` symbol, use ``private`` keyword instead.
120
121|CB_BAD|
122~~~~~~~~
123
124.. code-block:: typescript
125
126    class C {
127      foo = 1
128    }
129
130|CB_OK|
131~~~~~~~
132
133.. code-block:: typescript
134
135    class C {
136      private foo = 1
137    }
138
139
140.. _R004:
141
142|CB_R| #4: Use unique names for types, namespaces, etc.
143-------------------------------------------------------
144
145|CB_RULE|
146~~~~~~~~~
147
148Names for types, namespaces and so on must be unique and distinct from other
149names, e.g., variable names.
150
151|CB_BAD|
152~~~~~~~~
153
154.. code-block:: typescript
155
156    let X: string
157    type X = number[] // Type alias with the same name as the variable
158
159|CB_OK|
160~~~~~~~
161
162.. code-block:: typescript
163
164    let X: string
165    type T = number[] // X is not allowed here to avoid name collisions
166
167.. _R005:
168
169|CB_R| #5: Use ``let`` instead of ``var``
170-----------------------------------------
171
172|CB_RULE|
173~~~~~~~~~
174
175|LANG| does not support ``var``, always use ``let`` instead.
176
177|CB_BAD|
178~~~~~~~~
179
180.. code-block:: typescript
181
182    function f(shouldInitialize: boolean) {
183        if (shouldInitialize) {
184           var x = 10
185        }
186        return x
187    }
188
189    console.log(f(true))  // 10
190    console.log(f(false)) // undefined
191
192    let upper_let = 0
193    {
194        var scoped_var = 0
195        let scoped_let = 0
196        upper_let = 5
197    }
198    scoped_var = 5 // Visible
199    scoped_let = 5 // Compile-time error
200
201|CB_OK|
202~~~~~~~
203
204.. code-block:: typescript
205
206    function f(shouldInitialize: boolean): Object {
207        let x: Object = new Object();
208        if (shouldInitialize) {
209            x = 10
210        }
211        return x
212    }
213
214   console.log(f(true));  // 10
215   console.log(f(false)); // {}
216
217    let upper_let = 0
218    let scoped_var = 0
219    {
220        let scoped_let = 0
221        upper_let = 5
222    }
223    scoped_var = 5
224    scoped_let = 5 // Compile-time error
225
226.. _R008:
227
228|CB_R| #8: Use explicit types instead of ``any``, ``undefined``, ``unknown``
229----------------------------------------------------------------------------
230
231|CB_RULE|
232~~~~~~~~~
233
234|LANG| does not support ``any``, ``undefined``, and ``unknown`` types.
235Specify types explicitly.
236
237|CB_BAD|
238~~~~~~~~
239
240.. code-block:: typescript
241
242    var x
243    console.log(x) // undefined
244
245    var y: any
246    console.log(y) // undefined
247
248|CB_OK|
249~~~~~~~
250
251.. code-block:: typescript
252
253    // All variables should have their types specified explicitly:
254    let x: Object = {}
255    console.log(x) // {}
256
257|CB_SEE|
258~~~~~~~~
259
260.. _R009:
261
262|CB_R| #9: You can extend your |TS| code with more numeric types
263----------------------------------------------------------------
264
265|CB_RULE|
266~~~~~~~~~
267
268|LANG| supports different numeric types on top of just ``number``.
269
270|CB_BAD|
271~~~~~~~~
272
273|TS| supports ``number`` as the only numeric type:
274
275.. code-block:: typescript
276
277    let x: number = 1
278
279|CB_OK|
280~~~~~~~
281
282|LANG| supports several numeric types:
283
284+-----------+----------+-------------------------------------------------------------+
285| Type      | Size     | Range                                                       |
286+===========+==========+=============================================================+
287|``byte``   | 8 bits   |``[-128 .. 127]``                                            |
288+-----------+----------+-------------------------------------------------------------+
289|``short``  | 16 bits  |``[-32,768 .. 32,767]``                                      |
290+-----------+----------+-------------------------------------------------------------+
291|``int``    | 32 bits  |``[-2,147,483,648 .. 2,147,483,647]``                        |
292+-----------+----------+-------------------------------------------------------------+
293|``long``   | 64 bits  |``[-9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807]``|
294+-----------+----------+-------------------------------------------------------------+
295|``ubyte``  | 8 bits   |``[0 .. 255]``                                               |
296+-----------+----------+-------------------------------------------------------------+
297|``ushort`` | 16 bits  |``[0 .. 65,535]``                                            |
298+-----------+----------+-------------------------------------------------------------+
299|``uint``   | 32 bits  |``[0 .. 4,294,967,295]``                                     |
300+-----------+----------+-------------------------------------------------------------+
301|``ulong``  | 64 bits  |``[0 .. 18,446,744,073,709,551,615]``                        |
302+-----------+----------+-------------------------------------------------------------+
303|``float``  | 32 bits  |``3.4E +/- 38 (7 digits)``                                   |
304+-----------+----------+-------------------------------------------------------------+
305|``double`` | 64 bits  |``1.7E +/- 308 (15 digits)``                                 |
306+-----------+----------+-------------------------------------------------------------+
307
308Additionally, |LANG| supports the following types:
309
310* Character type ``char`` (the range of values is the same as ``ushort``)
311* Boolean type ``boolean`` (values: ``true``, ``false``)
312
313.. code-block:: typescript
314
315    let x: int = 1
316    let y: boolean = true
317    let z: char = 'a'
318
319.. _R010:
320
321|CB_R| #10: Use ``long`` instead of ``bigint``
322----------------------------------------------
323
324|CB_RULE|
325~~~~~~~~~
326
327Use ``long`` to work with 64-bit integers.
328
329|CB_BAD|
330~~~~~~~~
331
332|TS| supports ``bigint`` data type, but this feature is available only since
333ES2020 and requires ``n`` suffix for numeric literals:
334
335.. code-block:: typescript
336
337    let a: bigint = 1n
338
339|CB_OK|
340~~~~~~~
341
342|LANG| provides ``long`` data type to work with 64-bit
343integers, ``n`` suffix is not supported:
344
345.. code-block:: typescript
346
347    let x: long = 1
348
349.. _R012:
350
351|CB_R| #12: Use ``T[]`` instead of ``Array<T>`` to declare arrays
352-----------------------------------------------------------------
353
354|CB_RULE|
355~~~~~~~~~
356
357In |TS|, arrays can be declared as either ``Array<T>`` or ``T[]``. Currently,
358|LANG| supports only the second syntax for array declaration.
359
360|CB_BAD|
361~~~~~~~~
362
363.. code-block:: typescript
364
365    // These are equivalent in TypeScript:
366    let y: Array<string> = ["1", "2", "3"]
367
368|CB_OK|
369~~~~~~~
370
371.. code-block:: typescript
372
373   let x: string[] = ["1", "2", "3"];
374   let y: string[] = ["1", "2", "3"]; // Array<string> is not supported currently
375
376.. _R014:
377
378|CB_R| #14: Use ``class`` instead of a type with call signature
379---------------------------------------------------------------
380
381|CB_RULE|
382~~~~~~~~~
383
384|LANG| does not support call signatures in object types. Use classes instead.
385
386|CB_BAD|
387~~~~~~~~
388
389.. code-block:: typescript
390
391    type DescribableFunction = {
392        description: string
393        (someArg: number): string // call signature
394    }
395
396    function doSomething(fn: DescribableFunction): void {
397        console.log(fn.description + " returned " + fn(6))
398    }
399
400|CB_OK|
401~~~~~~~
402
403.. code-block:: typescript
404
405    class DescribableFunction {
406        description: string;
407        public invoke(someArg: number): string {
408            return someArg.toString()
409        }
410        constructor() {
411            this.description = "desc"
412        }
413    }
414
415    function doSomething(fn: DescribableFunction): void {
416        console.log(fn.description + " returned " + fn.invoke(6))
417    }
418
419    doSomething(new DescribableFunction());
420
421|CB_SEE|
422~~~~~~~~
423
424* :ref:`R015`
425
426.. _R015:
427
428|CB_R| #15: Use ``class`` instead of a type with constructor signature
429----------------------------------------------------------------------
430
431|CB_RULE|
432~~~~~~~~~
433
434|LANG| does not support constructor signatures in object types. Use classes
435instead.
436
437|CB_BAD|
438~~~~~~~~
439
440.. code-block:: typescript
441
442    class SomeObject {}
443
444    type SomeConstructor = {
445        new (s: string): SomeObject
446    }
447
448    function fn(ctor: SomeConstructor) {
449        return new ctor("hello");
450    }
451
452|CB_OK|
453~~~~~~~
454
455.. code-block:: typescript
456
457    class SomeObject {
458        public f: string
459        constructor (s: string) {
460            this.f = s
461        }
462    }
463
464    function fn(s: string): SomeObject {
465        return new SomeObject(s)
466    }
467
468|CB_SEE|
469~~~~~~~~
470
471* :ref:`R014`
472
473.. _R016:
474
475|CB_R| #16: Only one static block is supported
476----------------------------------------------
477
478|CB_RULE|
479~~~~~~~~~
480
481|LANG| does not allow to have sevaral static block for class initialization, combine static blocks statements to the one static block.
482
483|CB_BAD|
484~~~~~~~~
485
486.. code-block:: typescript
487
488    class C {
489        static s: string
490
491        static {
492            C.s = "aa"
493        }
494        static {
495            C.s = C.s + "bb"
496        }
497    }
498
499|CB_OK|
500~~~~~~~
501
502.. code-block:: typescript
503
504
505    class C {
506        static s: string
507
508        static {
509            C.s = "aa"
510            C.s = C.s + "bb"
511        }
512    }
513
514
515.. _R017:
516
517|CB_R| #17: Indexed signatures are not supported
518------------------------------------------------
519
520|CB_RULE|
521~~~~~~~~~
522
523|LANG| does not allow indexed signatures, use arrays instead.
524
525|CB_BAD|
526~~~~~~~~
527
528.. code-block:: typescript
529
530    // Interface with an indexed signature:
531    interface StringArray {
532        [index: number]: string
533    }
534
535    const myArray: StringArray = getStringArray()
536    const secondItem = myArray[1]
537
538|CB_OK|
539~~~~~~~
540
541.. code-block:: typescript
542
543    class X {
544        public f: string[]
545    }
546
547    let myArray: X = new X()
548    const secondItem = myArray.f[1]
549
550.. _R019:
551
552|CB_R| #19: Use inheritance instead of intersection types
553---------------------------------------------------------
554
555|CB_RULE|
556~~~~~~~~~
557
558Currently, |LANG| does not support intersection types. You can use inheritance
559as a work-around.
560
561|CB_BAD|
562~~~~~~~~
563
564.. code-block:: typescript
565
566    interface Identity {
567        id: number
568        name: string
569    }
570
571    interface Contact {
572        email: string
573        phone: string
574    }
575
576    type Employee = Identity & Contact
577
578|CB_OK|
579~~~~~~~
580
581.. code-block:: typescript
582
583    interface Identity {
584        id: number
585        name: string
586    }
587
588    interface Contact {
589        email: string
590        phone: string
591    }
592
593    interface Employee extends Identity,  Contact {}
594
595.. _R021:
596
597|CB_R| #21: Returning ``this`` type is not supported
598----------------------------------------------------
599
600|CB_RULE|
601~~~~~~~~~
602
603|LANG| does not support the returning ``this`` type. Use explicit type instead.
604
605|CB_BAD|
606~~~~~~~~
607
608.. code-block:: typescript
609
610    interface ListItem {
611        getHead(): this
612    }
613
614|CB_OK|
615~~~~~~~
616
617.. code-block:: typescript
618
619    interface ListItem {
620        getHead(): ListItem
621    }
622
623.. _R023:
624
625|CB_R| #22: Conditional types are not supported
626----------------------------------------------------
627
628|CB_RULE|
629~~~~~~~~~
630
631|LANG| does not support conditional type aliases. Introduce a new type with constraints explicitly or rewrite logic with use of ``Object``.
632``infer`` keyword is not supported.
633
634|CB_BAD|
635~~~~~~~~
636
637.. code-block:: typescript
638
639    type X<T> = T extends number ? T : never
640
641    type Y<T> = T extends Array<infer Item> ? Item : never
642
643|CB_OK|
644~~~~~~~
645
646.. code-block:: typescript
647
648    // Provide explicit contraints within type alias
649    type X1<T extends number> = T
650
651    // Rewrite with Object. Less type control, need more type checks for safety
652    type X2<T> = Object
653
654    // Item has to be used as a generic parameter and need to be properly instantiated
655    type YI<Item, T extends Array<Item>> = Item
656
657
658|CB_R| #23: Type queries are not supported
659------------------------------------------
660
661|CB_RULE|
662~~~~~~~~~
663
664Currently, |LANG| does not support specifying types via ``typeof``.
665All types must be specified explicitly.
666
667|CB_BAD|
668~~~~~~~~
669
670.. code-block:: typescript
671
672    var a = {x: 10, y: 20}
673    var b: typeof a
674
675|CB_OK|
676~~~~~~~
677
678.. code-block:: typescript
679
680    class A {
681        public x: number = 10
682        public y: number = 20
683    }
684
685    let a: A
686    let b: A
687
688.. _R025:
689
690|CB_R| #25: Declaring fields in ``constructor`` is not supported
691----------------------------------------------------------------
692
693|CB_RULE|
694~~~~~~~~~
695
696|LANG| does not support declaring class fields in the ``constructor``.
697You must declare them inside the ``class`` declaration instead.
698
699|CB_BAD|
700~~~~~~~~
701
702.. code-block:: typescript
703
704    class Person {
705        constructor(
706            protected ssn: string,
707            private firstName: string,
708            private lastName: string
709        ) {
710            this.ssn = ssn
711            this.firstName = firstName
712            this.lastName = lastName
713        }
714
715        getFullName(): string {
716            return this.firstName + " " + this.lastName
717        }
718    }
719
720|CB_OK|
721~~~~~~~
722
723.. code-block:: typescript
724
725   class Person {
726        protected ssn: string
727        private firstName: string
728        private lastName: string
729
730        constructor(ssn: string, firstName: string, lastName: string) {
731            this.ssn = ssn
732            this.firstName = firstName
733            this.lastName = lastName
734        }
735
736        getFullName(): string {
737            return this.firstName + " " + this.lastName
738        }
739    }
740
741.. _R027:
742
743|CB_R| #27: Construct signatures not supported in interfaces
744------------------------------------------------------------
745
746|CB_RULE|
747~~~~~~~~~
748
749|LANG| does not support construct signatures. Use methods instead.
750
751|CB_BAD|
752~~~~~~~~
753
754.. code-block:: typescript
755
756    interface I {
757        new (s: string): I
758    }
759
760    function fn(i: I) {
761        return new i("hello");
762    }
763
764|CB_OK|
765~~~~~~~
766
767.. code-block:: typescript
768
769    interface I {
770        create(s: string): I
771    }
772
773    function fn(i: I) {
774        return i.create("hello")
775    }
776
777|CB_SEE|
778~~~~~~~~
779
780* :ref:`R015`
781
782.. _R028:
783
784|CB_R| #28: Indexed access types are not supported
785--------------------------------------------------
786
787|CB_RULE|
788~~~~~~~~~
789
790|LANG| does not support indexed access types. Use the type name instead.
791
792|CB_BAD|
793~~~~~~~~
794
795.. code-block:: typescript
796
797    type Point = {x: number, y: number}
798    type N = Point["x"] // is equal to number
799
800|CB_OK|
801~~~~~~~
802
803.. code-block:: typescript
804
805    class Point {x: number = 0; y: number = 0}
806    type N = number
807
808.. _R029:
809
810|CB_R| #29: Indexed access is not supported for fields
811------------------------------------------------------
812
813|CB_RULE|
814~~~~~~~~~
815
816|LANG| does not support indexed access for class fields. Use dot notation instead.
817
818|CB_BAD|
819~~~~~~~~
820
821.. code-block:: typescript
822
823    class Point {x: number = 0; y: number = 0}
824    let p: Point = {x: 1, y: 2}
825    let x = p["x"]
826
827|CB_OK|
828~~~~~~~
829
830.. code-block:: typescript
831
832    class Point {x: number = 0; y: number = 0}
833    let p: Point = {x: 1, y: 2}
834    let x = p.x
835
836.. _R030:
837
838|CB_R| #30: Structural identity is not supported
839------------------------------------------------
840
841|CB_RULE|
842~~~~~~~~~
843
844Currently, |LANG| does not support structural identity, i.e., the compiler
845cannot compare two types' public APIs and decide whether such types are
846identical. Use other mechanisms (inheritance, interfaces or type aliases)
847instead.
848
849In |TS|, types ``X`` and ``Y`` are equal (interchangeble), while in |LANG|
850they are not.
851
852|CB_BAD|
853~~~~~~~~
854
855.. code-block:: typescript
856
857    interface X {
858        f(): string
859    }
860
861    interface Y { // Y is equal to X
862        f(): string
863    }
864
865|CB_OK|
866~~~~~~~
867
868|LANG| does not support structural identity. In the static environment the
869compiler checks if two classes or interfaces are equal, but there is no way
870to compare unrelated (by inheritance or interface) classes that are
871structurally equivalent.
872
873.. code-block:: typescript
874
875    interface X {
876        f(): string
877    }
878
879    type Y = X // Y is equal to X
880
881|CB_SEE|
882~~~~~~~~
883
884* :ref:`R031`
885* :ref:`R032`
886* :ref:`R035`
887
888
889.. _R031:
890
891|CB_R| #31: Structural typing is not supported for subtyping / supertyping
892--------------------------------------------------------------------------
893
894|CB_RULE|
895~~~~~~~~~
896
897Currently, |LANG| does not check structural equivalence for type inference, i.e.,
898the compiler cannot compare two types' public APIs and decide whether such types
899are identical.
900Use other mechanisms (inheritance or interfaces) instead.
901
902|CB_BAD|
903~~~~~~~~
904
905.. code-block:: typescript
906
907    class X {
908        public foo: number
909
910        constructor() {
911            this.foo = 0
912        }
913    }
914
915    class Y {
916        public foo: number
917
918        constructor() {
919            this.foo = 0
920        }
921    }
922
923    let x = new X()
924    let y = new Y()
925
926    console.log("Assign X to Y")
927    y = x
928
929    console.log("Assign Y to X")
930    x = y
931
932
933|CB_OK|
934~~~~~~~
935
936.. code-block:: typescript
937
938    class X {
939        public foo: number
940
941        constructor() {
942            this.foo = 0
943        }
944    }
945
946    // Y is derived from X, which explicitly set subtype / supertype relations:
947    class Y extends X {
948        constructor() {
949            super()
950        }
951    }
952
953    let x = new X()
954    let y = new Y()
955
956    console.log("Assign X to Y")
957    y = x // ok, X is the super class of X
958
959    // Cannot assign Y to X
960    //x = y - compile-time error
961
962
963|CB_SEE|
964~~~~~~~~
965
966* :ref:`R030`
967* :ref:`R032`
968* :ref:`R035`
969
970.. _R032:
971
972|CB_R| #32: Structural typing is not supported for assignability checks
973-----------------------------------------------------------------------
974
975|CB_RULE|
976~~~~~~~~~
977
978Currently, |LANG| does not check structural equivalence when checking if types
979are assignable to each other, i.e., the compiler cannot compare two types'
980public APIs and decide whether such types are identical. Use other mechanisms
981(inheritance or interfaces) instead.
982
983|CB_BAD|
984~~~~~~~~
985
986.. code-block:: typescript
987
988    class X {
989        public foo: number
990
991        constructor() {
992           this.foo = 0
993        }
994    }
995
996    class Y {
997        public foo: number
998        constructor() {
999            this.foo = 0
1000        }
1001    }
1002
1003    let x = new X()
1004    let y = new Y()
1005
1006    console.log("Assign X to Y")
1007    y = x
1008
1009    console.log("Assign Y to X")
1010    x = y
1011
1012|CB_OK|
1013~~~~~~~
1014
1015.. code-block:: typescript
1016
1017    interface Z {
1018       foo: number
1019    }
1020
1021    // X implements interface Z, which makes relation between X and Y explicit.
1022    class X implements Z {
1023        public foo: number
1024
1025        constructor() {
1026           this.foo = 0
1027        }
1028    }
1029
1030    // Y implements interface Z, which makes relation between X and Y explicit.
1031    class Y implements Z {
1032        public foo: number
1033
1034        constructor() {
1035           this.foo = 0
1036        }
1037    }
1038
1039    let x: Z = new X()
1040    let y: Z = new Y()
1041
1042    console.log("Assign X to Y")
1043    y = x // ok, both are of the same type
1044
1045    console.log("Assign Y to X")
1046    x = y // ok, both are of the same type
1047
1048|CB_SEE|
1049~~~~~~~~
1050
1051* :ref:`R030`
1052* :ref:`R031`
1053* :ref:`R035`
1054
1055.. _R034:
1056
1057|CB_R| #34: Generic functions must be called with explicit type specialization
1058------------------------------------------------------------------------------
1059
1060|CB_RULE|
1061~~~~~~~~~
1062
1063Currently, |LANG| does not support inference of type parameters in case of calls
1064to generic functions. If a function is declared generic, all calls must specify
1065type parameters explicitly.
1066
1067|CB_BAD|
1068~~~~~~~~
1069
1070.. code-block:: typescript
1071
1072    function choose<T>(x: T, y: T): T {
1073        return Math.random() < 0.5 ? x : y
1074    }
1075
1076    let x = choose(10, 20) // Ok
1077    let y = choose("10", 20) // Compile-time error
1078
1079|CB_OK|
1080~~~~~~~
1081
1082.. code-block:: typescript
1083
1084    function choose<T>(x: T, y: T): T {
1085        return Math.random() < 0.5 ? x : y
1086    }
1087
1088    let x = choose<number>(10, 20) // Ok
1089    let y = choose<number>("10", 20) // Compile-time error
1090
1091.. _R035:
1092
1093|CB_R| #35: Structural typing is not supported for type inference
1094-----------------------------------------------------------------
1095
1096|CB_RULE|
1097~~~~~~~~~
1098
1099Currently, |LANG| does not support structural typing, i.e., the compiler cannot
1100compare two types' public APIs and decide whether such types are identical.
1101Use inheritance and interfaces to specify the relation between the types
1102explicitly.
1103
1104|CB_BAD|
1105~~~~~~~~
1106
1107.. code-block:: typescript
1108
1109    class X  {
1110        public foo: number
1111        private s: string
1112
1113        constructor (f: number) {
1114            this.foo = f
1115            this.s = ""
1116        }
1117
1118        public say(): void {
1119           console.log("X = ", this.foo)
1120        }
1121    }
1122
1123    class Y {
1124        public foo: number
1125
1126        constructor (f: number) {
1127            this.foo = f
1128        }
1129        public say(): void {
1130            console.log("Y = ", this.foo)
1131        }
1132    }
1133
1134    function bar(z: X): void {
1135        z.say()
1136    }
1137
1138    // X and Y are equivalent because their public API is equivalent.
1139    // Thus the second call is allowed:
1140    bar(new X(1));
1141    bar(new Y(2));
1142
1143|CB_OK|
1144~~~~~~~
1145
1146.. code-block:: typescript
1147
1148    interface Z {
1149       say(): void
1150    }
1151
1152    class X implements Z {
1153        public foo: number
1154        private s: string
1155
1156        constructor (f: number) {
1157            this.foo = f
1158            this.s = ""
1159        }
1160        public say(): void {
1161            console.log("X = ", this.foo)
1162        }
1163    }
1164
1165    class Y implements Z {
1166        public foo: number
1167
1168        constructor (f: number) {
1169            this.foo = f
1170        }
1171        public say(): void {
1172            console.log("Y = ", this.foo)
1173        }
1174    }
1175
1176    function bar(z: Z): void {
1177        z.say()
1178    }
1179
1180    // X and Y implement the same interface Z, thus both calls are allowed:
1181    bar(new X(1))
1182    bar(new Y(2))
1183
1184|CB_SEE|
1185~~~~~~~~
1186
1187* :ref:`R030`
1188* :ref:`R031`
1189* :ref:`R032`
1190
1191.. _R037:
1192
1193|CB_R| #37: RegExp literals are not supported
1194---------------------------------------------
1195
1196|CB_RULE|
1197~~~~~~~~~
1198
1199Currently, |LANG| does not support RegExp literals. Use library call with string
1200literals instead.
1201
1202|CB_BAD|
1203~~~~~~~~
1204
1205.. code-block:: typescript
1206
1207   let regex: RegExp = /bc*d/
1208
1209|CB_OK|
1210~~~~~~~
1211
1212.. code-block:: typescript
1213
1214   let regex: RegExp = new RegExp("/bc*d/")
1215
1216.. _R038:
1217
1218|CB_R| #38: Object literal must correspond to explicitly declared class or interface
1219------------------------------------------------------------------------------------
1220
1221|CB_RULE|
1222~~~~~~~~~
1223
1224|LANG| supports the usage of object literals if the compiler can infer
1225to what classes or interfaces such literals correspond to. 
1226Otherwise, a compile-time error occurs.  
1227
1228The class or interface can be specified as a type annotation for a variable.
1229
1230|CB_BAD|
1231~~~~~~~~
1232
1233.. code-block:: typescript
1234
1235   let x = {f: 1}
1236
1237|CB_OK|
1238~~~~~~~
1239
1240.. code-block:: typescript
1241
1242    class O {
1243       f: number
1244    }
1245
1246    let x: O = {f: 1} // OK
1247    let y = {f: 1} // Compile-time error, cannot infer object literal type
1248    let z: Object = {f: 2} // Compile-time error, class 'Object' does not have field 'f'
1249
1250|CB_SEE|
1251~~~~~~~~
1252
1253* :ref:`R040`
1254* :ref:`R043`
1255
1256.. _R040:
1257
1258|CB_R| #40: Object literals cannot be used as type declarations
1259---------------------------------------------------------------
1260
1261|CB_RULE|
1262~~~~~~~~~
1263
1264|LANG| does not support the usage of object literals to declare
1265types in place. Declare classes and interfaces explicitly instead.
1266
1267|CB_BAD|
1268~~~~~~~~
1269
1270.. code-block:: typescript
1271
1272    let o: {x: number, y: number} = {
1273        x: 2,
1274        y: 3
1275    }
1276
1277    type T = G<{x: number, y: number}>
1278
1279|CB_OK|
1280~~~~~~~
1281
1282.. code-block:: typescript
1283
1284    class O {
1285        x: number
1286        y: number
1287    }
1288
1289    let o: O = {x: 2, y: 3}
1290
1291    type T = G<O>
1292
1293|CB_SEE|
1294~~~~~~~~
1295
1296* :ref:`R038`
1297* :ref:`R043`
1298
1299.. _R043:
1300
1301|CB_R| #43: Untyped array literals are not supported
1302----------------------------------------------------
1303
1304|CB_RULE|
1305~~~~~~~~~
1306
1307|LANG| does not support the usage of untyped array literals.  The type of an
1308array element must be inferred from the context. Use the type ``Object`` to
1309define mixed types array.
1310
1311|CB_BAD|
1312~~~~~~~~
1313
1314.. code-block:: typescript
1315
1316    let x = [1, 2]
1317    let y = [1, "aa"]
1318
1319|CB_OK|
1320~~~~~~~
1321
1322.. code-block:: typescript
1323
1324    let x: Object[] = [new Int(1), new Int(2)]
1325
1326    // Implicit boxing of primitive int to object Int
1327    let x1: Object[] = [1, 2]
1328
1329    let y: Object[] = [1, "aa"]
1330
1331|CB_SEE|
1332~~~~~~~~
1333
1334* :ref:`R038`
1335* :ref:`R040`
1336
1337.. _R044:
1338
1339|CB_R| #44: Template literals are not supported
1340-----------------------------------------------
1341
1342|CB_RULE|
1343~~~~~~~~~
1344
1345Currently, |LANG| does not support template literals. You may use a ``+``
1346concatenation as a work-around.
1347
1348|CB_BAD|
1349~~~~~~~~
1350
1351.. code-block:: typescript
1352
1353    const a = 5
1354    const b = 10
1355    console.log(`Fifteen is ${a + b}`)
1356
1357|CB_OK|
1358~~~~~~~
1359
1360.. code-block:: typescript
1361
1362    const a = 5
1363    const b = 10
1364
1365    // (a + b) is converted to Int and then toString() method is called:
1366    console.log("Fifteen is " + (a + b))
1367
1368.. _R045:
1369
1370|CB_R| #45: Lambdas require explicit type annotation for parameters
1371-------------------------------------------------------------------
1372
1373|CB_RULE|
1374~~~~~~~~~
1375
1376Currently, |LANG| requires the types of lambda parameters 
1377to be explicitly specified.
1378
1379|CB_BAD|
1380~~~~~~~~
1381
1382.. code-block:: typescript
1383
1384    let f = (s) => { // type any is assumed
1385            console.log(s)
1386        }
1387
1388|CB_OK|
1389~~~~~~~
1390
1391Explicit types for lambda parameters are mandatory.
1392
1393.. code-block:: typescript
1394
1395    let f =
1396        (s: string) => {
1397            console.log(s)
1398        }
1399
1400|CB_SEE|
1401~~~~~~~~
1402
1403* :ref:`R047`
1404
1405.. _R046:
1406
1407|CB_R| #46: Use arrow functions instead of function expressions
1408-------------------------------------------------------------------
1409
1410|CB_RULE|
1411~~~~~~~~~
1412
1413|LANG| does not support function expressions, use arrow functions instead
1414to be explicitly specified.
1415
1416|CB_BAD|
1417~~~~~~~~
1418
1419.. code-block:: typescript
1420
1421    let f = function (s: string) { 
1422            console.log(s)
1423        }
1424
1425|CB_OK|
1426~~~~~~~
1427
1428.. code-block:: typescript
1429
1430    let f = (s: string) => {
1431            console.log(s)
1432        }
1433
1434.. _R047:
1435
1436|CB_R| #47: Return type must be specified for lambdas explicitly
1437----------------------------------------------------------------
1438
1439|CB_RULE|
1440~~~~~~~~~
1441
1442An explicit return type is mandatory for a lambda expression.
1443
1444|CB_BAD|
1445~~~~~~~~
1446
1447.. code-block:: typescript
1448
1449    let f = (s: string) => { // return type is implicit
1450            return s.toLowerCase()
1451        }
1452
1453|CB_OK|
1454~~~~~~~
1455
1456.. code-block:: typescript
1457
1458    let f = (s: string): string => { // return type is explicit
1459            return s.toLowerCase()
1460        }
1461
1462|CB_SEE|
1463~~~~~~~~
1464
1465* :ref:`R045`
1466
1467.. _R049:
1468
1469|CB_R| #49: Usage of arrow function with type assertions or generics
1470--------------------------------------------------------------------
1471
1472|CB_BAD|
1473~~~~~~~~
1474
1475A non-compliant syntax is used. Not a part of the common subset.
1476
1477.. code-block:: typescript
1478
1479    let generic_arrow_func =
1480        <T extends String> (x: T) => { return x }
1481    let type_asserted_function =
1482        <() => boolean> (() => {return true})
1483
1484    generic_arrow_func(5) // Compile-time error
1485    generic_arrow_func("string")
1486    type_asserted_function()
1487
1488|CB_OK|
1489~~~~~~~
1490
1491Introduce a new function to replace an arrow function with generics.
1492Explicit types are mandatory, static typing replaces type assertions by design.
1493
1494.. code-block:: typescript
1495
1496    function generic_arrow_func<T extends String>(x: T): T {
1497        return x
1498    }
1499
1500    let type_asserted_func: () => boolean =
1501        (): boolean => {return true}
1502
1503    generic_arrow_func(5) // Compile-time error
1504    generic_arrow_func("string")
1505
1506    type_asserted_func()
1507
1508.. _R050:
1509
1510|CB_R| #50: Class literals are not supported
1511--------------------------------------------
1512
1513|CB_RULE|
1514~~~~~~~~~
1515
1516|LANG| does not support class literals. A new named class type must be
1517introduced explicitly.
1518
1519|CB_BAD|
1520~~~~~~~~
1521
1522.. code-block:: typescript
1523
1524    const Rectangle = class {
1525        constructor(height: number, width: number) {
1526            this.heigth = height
1527            this.width = width
1528        }
1529
1530        heigth
1531        width
1532    }
1533
1534    const rectangle = new Rectangle(0.0, 0.0)
1535
1536|CB_OK|
1537~~~~~~~
1538
1539.. code-block:: typescript
1540
1541    class Rectangle {
1542        constructor(height: number, width: number) {
1543            this.heigth = height
1544            this.width = width
1545        }
1546
1547        heigth: number
1548        width: number
1549    }
1550
1551    const rectangle = new Rectangle(0.0, 0.0)
1552
1553.. _R051:
1554
1555|CB_R| #51: Classes cannot be specified in ``implements`` clause
1556----------------------------------------------------------------
1557
1558|CB_RULE|
1559~~~~~~~~~
1560
1561|LANG| does not allow to specify a class in implements clause. Only interfaces may be specified.
1562
1563|CB_BAD|
1564~~~~~~~~
1565
1566.. code-block:: typescript
1567
1568    class C {
1569      foo() {}
1570    }
1571    
1572    class C1 implements C {
1573      foo() {}
1574    }
1575
1576|CB_OK|
1577~~~~~~~
1578
1579.. code-block:: typescript
1580
1581    interface C {
1582      foo()
1583    }
1584    
1585    class C1 implements C {
1586      foo() {}
1587    }
1588
1589
1590.. _R052:
1591
1592|CB_R| #52: Attempt to access an undefined property is a compile-time error
1593---------------------------------------------------------------------------
1594
1595|CB_RULE|
1596~~~~~~~~~
1597
1598|LANG| supports accessing only those class properties that are either declared
1599in the class, or accessible via inheritance. Accessing any other properties is
1600prohibited and causes compile-time errors.
1601
1602|CB_BAD|
1603~~~~~~~~
1604
1605.. code-block:: typescript
1606
1607    let person = {name: "Bob", isEmployee: true}
1608
1609    let n = typ["name"]
1610    let e = typ["isEmployee"]
1611    let s = typ["office"] // undefined
1612
1613|CB_OK|
1614~~~~~~~
1615
1616Use proper types to check property existence during compilation.
1617
1618.. code-block:: typescript
1619
1620    class Person {
1621        constructor(name: string, isEmployee: boolean) {
1622            this.name = name
1623            this.isEmployee = isEmployee
1624        }
1625
1626        name: string
1627        isEmployee: boolean
1628    }
1629
1630    let person = new Person("Bob", true)
1631    let n = typ.name
1632    let e = typ.isEmployee
1633    let s = typ.office // Compile-time error
1634
1635|CB_SEE|
1636~~~~~~~~
1637
1638* :ref:`R001`
1639* :ref:`R002`
1640* :ref:`R059`
1641* :ref:`R060`
1642* :ref:`R066`
1643* :ref:`R105`
1644* :ref:`R109`
1645
1646.. _R053:
1647
1648|CB_R| #53: Only ``as T`` syntax is supported for type casts
1649------------------------------------------------------------
1650
1651|CB_RULE|
1652~~~~~~~~~
1653
1654|LANG| supports ``as`` keyword as the only syntax for type casts.
1655Incorrect cast causes a compile-time error or runtime ``ClassCastError``.
1656``<type>`` syntax for type casts is not supported.
1657
1658|CB_BAD|
1659~~~~~~~~
1660
1661.. code-block:: typescript
1662
1663    class Shape {}
1664    class Circle extends Shape {x: number = 5}
1665    class Square extends Shape {y: string = "a"}
1666
1667    function createShape(): Shape {
1668        return new Circle()
1669    }
1670
1671    let c1 = <Circle> createShape()
1672
1673    let c2 = createShape() as Circle
1674
1675    // No report is provided during compilation
1676    // nor during runtime if cast is wrong:
1677    let c3 = createShape() as Square
1678    console.log(c3.y) // undefined
1679
1680|CB_OK|
1681~~~~~~~
1682
1683.. code-block:: typescript
1684
1685    class Shape {}
1686    class Circle extends Shape {x: number = 5}
1687    class Square extends Shape {y: string = "a"}
1688
1689    function createShape(): Shape {
1690        return new Circle()
1691    }
1692
1693    let c2 = createShape() as Circle
1694
1695    // ClassCastError during runtime is thrown:
1696    let c3 = createShape() as Square
1697
1698.. _R054:
1699
1700|CB_R| #54: JSX expressions are not supported
1701---------------------------------------------
1702
1703|CB_RULE|
1704~~~~~~~~~
1705
1706Do not use JSX since no alternative is provided to rewrite it.
1707
1708.. _R055:
1709
1710|CB_R| #55: Unary operators ``+``, ``-`` and ``~`` work only on numbers
1711-----------------------------------------------------------------------
1712
1713|CB_RULE|
1714~~~~~~~~~
1715
1716|LANG| allows unary operators to work on numeric types only. A compile-time
1717error occurs if these operators are applied to a non-numeric type. Unlike in
1718|TS|, implicit casting of strings in this context is not supported and must
1719be done explicitly.
1720
1721|CB_BAD|
1722~~~~~~~~
1723
1724.. code-block:: typescript
1725
1726    let a = +5   // 5 as number
1727    let b = +"5" // 5 as number
1728    let c = -5   // -5 as number
1729    let d = -"5" // -5 as number
1730    let e = ~5   // -6 as number
1731    let f = ~"5" // -6 as number
1732    let g = +"string" // NaN as number
1733
1734|CB_OK|
1735~~~~~~~
1736
1737.. code-block:: typescript
1738
1739    let a = +5   // 5 as int
1740    let b = +"5" // Compile-time error
1741    let c = -5   // -5 as int
1742    let d = -"5" // Compile-time error
1743    let e = ~5   // -6 as int
1744    let f = ~"5" // Compile-time error
1745    let g = +"string" // Compile-time error
1746
1747|CB_SEE|
1748~~~~~~~~
1749
1750* :ref:`R055`
1751* :ref:`R057`
1752* :ref:`R061`
1753* :ref:`R062`
1754* :ref:`R063`
1755* :ref:`R064`
1756* :ref:`R067`
1757* :ref:`R068`
1758* :ref:`R078`
1759
1760.. _R056:
1761
1762|CB_R| #56: Unary ``+`` cannot be used for casting to ``number``
1763----------------------------------------------------------------
1764
1765|CB_RULE|
1766~~~~~~~~~
1767
1768|LANG| does not support casting from any type to a numeric type
1769by using the unary ``+`` operator, which can be applied only to
1770numeric types.
1771
1772|CB_BAD|
1773~~~~~~~~
1774
1775.. code-block:: typescript
1776
1777    function returnTen(): string {
1778        return "-10"
1779    }
1780
1781    function returnString(): string {
1782        return "string"
1783    }
1784
1785    let a = +returnTen()    // -10 as number
1786    let b = +returnString() // NaN
1787
1788|CB_OK|
1789~~~~~~~
1790
1791.. code-block:: typescript
1792
1793    function returnTen(): string {
1794        return "-10"
1795    }
1796
1797    function returnString(): string {
1798        return "string"
1799    }
1800
1801    let a = +returnTen()    // Compile-time error
1802    let b = +returnString() // Compile-time error
1803
1804|CB_SEE|
1805~~~~~~~~
1806
1807* :ref:`R055`
1808* :ref:`R057`
1809* :ref:`R061`
1810* :ref:`R062`
1811* :ref:`R063`
1812* :ref:`R064`
1813* :ref:`R067`
1814* :ref:`R068`
1815* :ref:`R078`
1816
1817.. _R057:
1818
1819|CB_R| #57: ``!`` operator works only on values of the boolean type
1820-------------------------------------------------------------------
1821
1822|CB_RULE|
1823~~~~~~~~~
1824
1825|LANG| supports using ``!`` operator only for values of the boolean type.
1826Explicit cast from some type to the boolean (or Boolean) is mandatory.
1827Implicit casts are prohibited and cause compile-time errors.
1828
1829|CB_BAD|
1830~~~~~~~~
1831
1832.. code-block:: typescript
1833
1834    let a = !true      // false
1835    let b = !"true"    // false
1836    let c = !"rnd_str" // false
1837    let d = !"false"   // false
1838    let e = !5         // false
1839    let f = !0         // true
1840
1841|CB_OK|
1842~~~~~~~
1843
1844.. code-block:: typescript
1845
1846    let a = !true      // false
1847    let b = !"true"    // Compile-time error
1848    let c = !"false"   // Compile-time error
1849    let d = !"rnd_str" // Compile-time error
1850    let e = !5         // Compile-time error
1851    let f = !0         // Compile-time error
1852
1853|CB_SEE|
1854~~~~~~~~
1855
1856* :ref:`R055`
1857* :ref:`R056`
1858* :ref:`R061`
1859* :ref:`R062`
1860* :ref:`R063`
1861* :ref:`R064`
1862* :ref:`R067`
1863* :ref:`R068`
1864* :ref:`R078`
1865
1866.. _R059:
1867
1868|CB_R| #59: ``delete`` operator is not supported
1869------------------------------------------------
1870
1871|CB_RULE|
1872~~~~~~~~~
1873
1874|LANG| assumes that object layout is known at compile time and cannot be 
1875changed at runtime. Thus the operation of deleting a property makes no sense.
1876
1877|CB_BAD|
1878~~~~~~~~
1879
1880.. code-block:: typescript
1881
1882    class Point {
1883        x?: number = 0.0
1884        y?: number = 0.0
1885    }
1886
1887    let p = new Point()
1888    delete p.y
1889
1890|CB_OK|
1891~~~~~~~
1892
1893.. code-block:: typescript
1894
1895    // To mimic the original semantics, you may declare a nullable type
1896    // and assign null to mark value absence:
1897
1898    class Point {
1899        x: number | null
1900        y: number | null
1901    }
1902
1903    let p = new Point()
1904    p.y = null
1905
1906|CB_SEE|
1907~~~~~~~~
1908
1909* :ref:`R001`
1910* :ref:`R002`
1911* :ref:`R052`
1912* :ref:`R060`
1913* :ref:`R066`
1914* :ref:`R105`
1915* :ref:`R109`
1916
1917.. _R060:
1918
1919|CB_R| #60: ``typeof`` is allowed only in expression contexts
1920-------------------------------------------------------------
1921
1922|CB_RULE|
1923~~~~~~~~~
1924
1925|LANG| supports ``typeof`` operator only in the expression context.
1926Type notation with ``typeof`` is not supported.
1927
1928|CB_BAD|
1929~~~~~~~~
1930
1931.. code-block:: typescript
1932
1933    let n1 = 42
1934    let s1 = "foo"
1935    console.log(typeof n1) // "number"
1936    console.log(typeof s1) // "string"
1937    let n2: typeof n1
1938    let s2: typeof s1
1939
1940|CB_OK|
1941~~~~~~~
1942
1943.. code-block:: typescript
1944
1945    let n1 = 42
1946    let s1 = "foo"
1947    console.log(typeof n1) // "number"
1948    console.log(typeof s1) // "string"
1949    let n2: number
1950    let s2: string
1951
1952|CB_SEE|
1953~~~~~~~~
1954
1955* :ref:`R001`
1956* :ref:`R002`
1957* :ref:`R052`
1958* :ref:`R059`
1959* :ref:`R066`
1960* :ref:`R105`
1961* :ref:`R109`
1962
1963.. _R061:
1964
1965|CB_R| #61: Binary operators ``*``, ``/``, ``%``, ``-``, ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on numeric types
1966-----------------------------------------------------------------------------------------------------------------------------------
1967
1968|CB_RULE|
1969~~~~~~~~~
1970
1971|LANG| allows applying binary operators ``*``, ``/``, ``%``, ``-``, ``<<``,
1972``>>``, ``>>>``, ``&``, ``^`` and ``|`` only to values of numeric types.
1973Implicit casts from other types to numeric types are prohibited and cause
1974compile-time errors.
1975
1976|CB_BAD|
1977~~~~~~~~
1978
1979.. code-block:: typescript
1980
1981    let a = (5 & 5)     // 5
1982    let b = (5.5 & 5.5) // 5, not 5.5
1983    let c = (5 | 5)     // 5
1984    let d = (5.5 | 5.5) // 5, not 5.5
1985
1986    enum Direction {
1987        Up = -1,
1988        Down
1989    }
1990    let e = Direction.Up >> 1 // -1
1991    let f = Direction.Up >>> 1 // 2147483647
1992
1993    let g = ("10" as any) << 1  // 20
1994    let h = ("str" as any) << 1 // 0
1995
1996    let i = 10 * 5
1997    let j = 10 / 5
1998    let k = 10 % 5
1999    let l = 10 - 5
2000
2001|CB_OK|
2002~~~~~~~
2003
2004.. code-block:: typescript
2005
2006    let a = (5 & 5)     // 5
2007    let b = (5.5 & 5.5) // Compile-time error
2008    let c = (5 | 5)     // 5
2009    let d = (5.5 | 5.5) // Compile-time error
2010
2011    enum Direction {
2012        Up, // TBD: explicit start value
2013        Down
2014    }
2015
2016    let e = Direction.Up >> 1  // 0
2017    let f = Direction.Up >>> 1 // 0
2018
2019    let i = 10 * 5
2020    let j = 10 / 5
2021    let k = 10 % 5
2022    let l = 10 - 5
2023
2024|CB_SEE|
2025~~~~~~~~
2026
2027* :ref:`R055`
2028* :ref:`R056`
2029* :ref:`R057`
2030* :ref:`R062`
2031* :ref:`R063`
2032* :ref:`R064`
2033* :ref:`R067`
2034* :ref:`R068`
2035* :ref:`R078`
2036
2037.. _R062:
2038
2039|CB_R| #62: Binary operators ``<<``, ``>>``, ``>>>``, ``&``, ``^`` and ``|`` work only on integral numeric types
2040----------------------------------------------------------------------------------------------------------------
2041
2042|CB_RULE|
2043~~~~~~~~~
2044
2045|LANG| expects an explicit cast to an integral type for logical binary
2046operations. Implicit casts are prohibited and cause compile-time errors.
2047
2048|CB_BAD|
2049~~~~~~~~
2050
2051.. code-block:: typescript
2052
2053    let b = (5.5 & 5.5) // 5, not 5.5
2054    let d = (5.5 | 5.5) // 5, not 5.5
2055
2056    let g = ("10" as any) << 1  // 20
2057    let h = ("str" as any) << 1 // 0
2058
2059|CB_OK|
2060~~~~~~~
2061
2062.. code-block:: typescript
2063
2064    let b = (5.5 & 5.5) // Compile-time error
2065    let d = (5.5 | 5.5) // Compile-time error
2066
2067|CB_SEE|
2068~~~~~~~~
2069
2070* :ref:`R055`
2071* :ref:`R056`
2072* :ref:`R057`
2073* :ref:`R061`
2074* :ref:`R063`
2075* :ref:`R064`
2076* :ref:`R067`
2077* :ref:`R068`
2078* :ref:`R078`
2079
2080.. _R063:
2081
2082|CB_R| #63: Binary ``+`` operator supports implicit casts only for numbers and strings
2083--------------------------------------------------------------------------------------
2084
2085|CB_RULE|
2086~~~~~~~~~
2087
2088|LANG| supports implicit casts for ``+`` only for strings and numbers.
2089Elsewhere, any form of an explicit cast to string is required.
2090
2091|CB_BAD|
2092~~~~~~~~
2093
2094.. code-block:: typescript
2095
2096    enum E { E1, E2 }
2097
2098    let a = 10 + 32   // 42
2099    let b = E.E1 + 10 // 10
2100    let c = 10 + "5"  // "105"
2101
2102    let d = "5" + E.E2 // "51"
2103    let e = "Hello, " + "world!" // "Hello, world!"
2104    let f = "string" + true // "stringtrue"
2105
2106    let g = (new Object()) + "string" // "[object Object]string"
2107
2108|CB_OK|
2109~~~~~~~
2110
2111.. code-block:: typescript
2112
2113    enum E { E1, E2 }
2114
2115    let a = 10 + 32   // 42
2116    let b = E.E1 + 10 // 10
2117    let c = 10 + "5"  // "105"
2118
2119    let d = "5" + E.E2 // "51"
2120    let e = "Hello, " + "world!" // "Hello, world!"
2121    let f = "string" + true // "stringtrue"
2122
2123    let g = (new Object()).toString() + "string"
2124
2125|CB_SEE|
2126~~~~~~~~
2127
2128* :ref:`R055`
2129* :ref:`R056`
2130* :ref:`R057`
2131* :ref:`R061`
2132* :ref:`R062`
2133* :ref:`R064`
2134* :ref:`R067`
2135* :ref:`R068`
2136* :ref:`R078`
2137
2138.. _R064:
2139
2140|CB_R| #64: Binary ``+`` operator requires explicit casts for non-numbers and non-strings
2141-----------------------------------------------------------------------------------------
2142
2143|CB_RULE|
2144~~~~~~~~~
2145
2146|LANG| supports implicit casts for ``+`` only for strings and numbers.
2147Elsewhere, any form of an explicit cast to string is required.
2148
2149|CB_BAD|
2150~~~~~~~~
2151
2152.. code-block:: typescript
2153
2154    // "[object Object][object Object]"
2155    let o = ({x: 5} as any) + {y: 6}
2156
2157|CB_OK|
2158~~~~~~~
2159
2160.. code-block:: typescript
2161
2162    let o = (new Object()).toString() + new Int(5) // "5"
2163
2164|CB_SEE|
2165~~~~~~~~
2166
2167* :ref:`R055`
2168* :ref:`R056`
2169* :ref:`R057`
2170* :ref:`R061`
2171* :ref:`R062`
2172* :ref:`R063`
2173* :ref:`R067`
2174* :ref:`R068`
2175* :ref:`R078`
2176
2177|CB_R| #65: ``instanceof`` operator is partially supported
2178----------------------------------------------------------
2179
2180|CB_RULE|
2181~~~~~~~~~
2182
2183In |TS|, the left-hand side of an ``instanceof`` expression must be of type
2184``any``, an object type or a type parameter, otherwise the result is ``false``.
2185In |LANG|, the left-hand side expression may be of any reference type, otherwise
2186a compile-time error occurs. In addition, the left operand in |LANG| cannot be
2187a type.
2188
2189|CB_BAD|
2190~~~~~~~~
2191
2192.. code-block:: typescript
2193
2194    class X {}
2195
2196    let a = (new X()) instanceof Object // true
2197    let b = (new X()) instanceof X // true
2198    // left operand is a type:
2199    let c = X instanceof Object // true
2200    let d = X instanceof X // false
2201
2202    // left operand is not of type any
2203    let e = (5.0 as Number) instanceof Number // false
2204
2205|CB_OK|
2206~~~~~~~
2207
2208.. code-block:: typescript
2209
2210    class X {}
2211
2212    let a = (new X()) instanceof Object // true
2213    let b = (new X()) instanceof X // true
2214    // left operand is a type:
2215    let c = X instanceof Object // Compile-time error
2216    let d = X instanceof X // Compile-time error
2217
2218    // left operand may be of any reference type, like number
2219    let e = (5.0 as Number) instanceof Number // true
2220
2221.. _R066:
2222
2223|CB_R| #66: ``in`` operator is not supported
2224--------------------------------------------
2225
2226|CB_RULE|
2227~~~~~~~~~
2228
2229|LANG| does not support the ``in`` operator. However, this operator makes
2230little sense since the object layout is known at compile time and cannot
2231be modified at runtime. Use ``instanceof`` as a work-around if you still need
2232to check whether certain class members exist.
2233
2234|CB_BAD|
2235~~~~~~~~
2236
2237.. code-block:: typescript
2238
2239    class Person {
2240        name: string = ""
2241    }
2242    let p = new Person()
2243
2244    let b = "name" in p // true
2245
2246|CB_OK|
2247~~~~~~~
2248
2249.. code-block:: typescript
2250
2251    class Person {
2252        name: string = ""
2253    }
2254    let p = new Person()
2255
2256    let b = p instanceof Person // true, and "name" is guaranteed to be present
2257
2258|CB_SEE|
2259~~~~~~~~
2260
2261* :ref:`R001`
2262* :ref:`R002`
2263* :ref:`R052`
2264* :ref:`R059`
2265* :ref:`R060`
2266* :ref:`R105`
2267* :ref:`R109`
2268
2269.. _R067:
2270
2271|CB_R| #67: Operators ``&&`` and ``||`` work on values of the boolean type only
2272-------------------------------------------------------------------------------
2273
2274|CB_RULE|
2275~~~~~~~~~
2276
2277|LANG| supports using ``&&`` and ``||`` operators only for the values of the
2278boolean type. Explicit cast from some type to the boolean (or Boolean) is
2279mandatory. Implicit casts are prohibited and cause compile-time errors.
2280
2281|CB_BAD|
2282~~~~~~~~
2283
2284.. code-block:: typescript
2285
2286    let a = true && false // false
2287    let b = 5 || 0        // 5
2288    let c = 5 && 0        // 0
2289    let d = "" && 5       // ""
2290    let e = "" || "abcd"  // "abcd"
2291
2292|CB_OK|
2293~~~~~~~
2294
2295.. code-block:: typescript
2296
2297    let a = true && false // false
2298    let b = 5 || 0        // Compile-time error
2299    let c = 5 && 0        // Compile-time error
2300    let d = "" && 5       // Compile-time error
2301    let e = "" || "abcd"  // Compile-time error
2302
2303|CB_SEE|
2304~~~~~~~~
2305
2306* :ref:`R055`
2307* :ref:`R056`
2308* :ref:`R057`
2309* :ref:`R061`
2310* :ref:`R062`
2311* :ref:`R063`
2312* :ref:`R064`
2313* :ref:`R068`
2314* :ref:`R078`
2315
2316.. _R068:
2317
2318|CB_R| #68: Using of ``&&`` and ``||`` on non-boolean types is not supported
2319----------------------------------------------------------------------------
2320
2321|CB_RULE|
2322~~~~~~~~~
2323
2324|LANG| supports the usage of ``&&`` and ``||`` operators only for the values
2325of the boolean type. Explicit cast from some type to the boolean (or Boolean)
2326is mandatory. Implicit casts are prohibited and cause compile-time errors.
2327
2328|CB_BAD|
2329~~~~~~~~
2330
2331.. code-block:: typescript
2332
2333    let a = true && false // false
2334    let b = 5 || 0        // 5
2335    let c = 5 && 0        // 0
2336    let d = "" && 5       // ""
2337    let e = "" || "abcd"  // "abcd"
2338
2339|CB_OK|
2340~~~~~~~
2341
2342.. code-block:: typescript
2343
2344    let a = true && false // false
2345    let b = 5 || 0        // Compile-time error
2346    let c = 5 && 0        // Compile-time error
2347    let d = "" && 5       // Compile-time error
2348    let e = "" || "abcd"  // Compile-time error
2349
2350|CB_SEE|
2351~~~~~~~~
2352
2353* :ref:`R055`
2354* :ref:`R056`
2355* :ref:`R057`
2356* :ref:`R061`
2357* :ref:`R062`
2358* :ref:`R063`
2359* :ref:`R064`
2360* :ref:`R067`
2361* :ref:`R078`
2362
2363.. _R069:
2364
2365|CB_R| #69: Destructuring assignment is not supported
2366-----------------------------------------------------
2367
2368|CB_RULE|
2369~~~~~~~~~
2370
2371|LANG| does not support destructuring assignment. Other idioms (e.g.,
2372using a temporary variable, where applicable) can be used for replacement.
2373
2374|CB_BAD|
2375~~~~~~~~
2376
2377.. code-block:: typescript
2378
2379    let [one, two] = [1, 2]
2380    [one, two] = [two, one]
2381
2382    let head, tail
2383    [head, ...tail] = [1, 2, 3, 4]
2384
2385|CB_OK|
2386~~~~~~~
2387
2388.. code-block:: typescript
2389
2390    let arr: number[] = [1, 2]
2391    let one = arr[0]
2392    let two = arr[1]
2393
2394    let tmp = one
2395    one = two
2396    two = tmp
2397
2398    let data: Number[] = [1,2,3,4]
2399    let head = data[0]
2400    let tail = new Number[data.length - 1]
2401    for (let i = 1; i < data.length; ++i) {
2402        tail[i-1] = data[i]
2403    }
2404
2405.. _R071:
2406
2407|CB_R| #71: The comma operator ``,`` is supported only in ``for`` loops
2408-----------------------------------------------------------------------
2409
2410|CB_RULE|
2411~~~~~~~~~
2412
2413|LANG| supports the comma operator ``,`` only in ``for`` loops. Otherwise,
2414it is useless as it makes the execution order harder to understand.
2415
2416|CB_BAD|
2417~~~~~~~~
2418
2419.. code-block:: typescript
2420
2421    for (let i = 0, j = 0; i < 10; ++i, j += 2) {
2422        console.log(i, j)
2423    }
2424
2425    let x = 0
2426    x = (++x, x++) // 1
2427
2428|CB_OK|
2429~~~~~~~
2430
2431.. code-block:: typescript
2432
2433    for (let i = 0, j = 0; i < 10; ++i, j += 2) {
2434        console.log(i, j)
2435    }
2436
2437    // Use explicit execution order instead of the comma operator:
2438    let x = 0
2439    ++x
2440    x = x++
2441
2442.. _R073:
2443
2444|CB_R| #74: Destructuring variable declarations are not supported
2445-----------------------------------------------------------------
2446
2447|CB_RULE|
2448~~~~~~~~~
2449
2450|LANG| does not support destructuring variable declarations. This is a dynamic
2451feature relying on structural compatibility. In addition, names in destructuring
2452declarations must be equal to properties within destructured classes.
2453
2454|CB_BAD|
2455~~~~~~~~
2456
2457.. code:: typescript
2458
2459    class Point {
2460        x: number = 0.0
2461        y: number = 0.0
2462    }
2463
2464    function returnZeroPoint(): Point {
2465        return new Point()
2466    }
2467
2468    let {x, y} = returnZeroPoint()
2469
2470|CB_OK|
2471~~~~~~~
2472
2473.. code:: typescript
2474
2475    class Point {
2476        x: number = 0.0
2477        y: number = 0.0
2478    }
2479
2480    function returnZeroPoint(): Point {
2481        return new Point()
2482    }
2483
2484    // Create an intermediate object and work with it field by field
2485    // without name restrictions:
2486    let zp = returnZeroPoint()
2487    let x = zp.x
2488    let y = zp.y
2489
2490.. _R076:
2491
2492|CB_R| #76: Inference of implied types is not supported
2493-------------------------------------------------------
2494
2495|CB_RULE|
2496~~~~~~~~~
2497
2498Currently, |LANG| does not support inference of implied types. Use explicit
2499type notation instead. Use ``Object[]`` if you need containers that hold
2500data of mixed types.
2501
2502|CB_BAD|
2503~~~~~~~~
2504
2505.. code-block:: typescript
2506
2507    let [a, b, c] = [1, "hello", true]
2508
2509|CB_OK|
2510~~~~~~~
2511
2512.. code-block:: typescript
2513
2514    let a = 1
2515    let b = "hello"
2516    let c = true
2517
2518    let arr: Object[] = [1, "hello", true]
2519    let a1 = arr[0]
2520    let b1 = arr[1]
2521    let c1 = arr[2]
2522
2523.. _R078:
2524
2525|CB_R| #78: Implicit casts to the boolean are not supported in ``if``, ``do`` and ``while``
2526-------------------------------------------------------------------------------------------
2527
2528|CB_RULE|
2529~~~~~~~~~
2530
2531|LANG| supports only values of the boolean type in ``if``, ``do`` and ``while``
2532statements. Implicit casts from other types to the boolean are prohibited and
2533cause compile-time errors.
2534
2535|CB_BAD|
2536~~~~~~~~
2537
2538.. code-block:: typescript
2539
2540    if (true) {}
2541    do {} while (false)
2542
2543    let a = new Boolean(true)
2544    if (a) {}
2545    do {break} while (a)
2546    while (a) {break}
2547
2548    let b = 42
2549    if (b) {}
2550    do {break} while (b)
2551    while (b) {break}
2552
2553    let c = "str"
2554    if (c) {}
2555    do {break} while (c)
2556    while (c) {break}
2557
2558    let d = new Object()
2559    if (d) {}
2560    do {break} while (d)
2561    while (d) {break}
2562
2563|CB_OK|
2564~~~~~~~
2565
2566.. code-block:: typescript
2567
2568    if (true) {}
2569    do {} while (false)
2570
2571    let a = new Boolean(true)
2572    if (a) {}
2573    do {break} while (a)
2574    while (a) {break}
2575
2576    let b = 42
2577    if (b != 0) {}
2578    do {break} while (b != 0)
2579    while (b != 0) {break}
2580
2581    let c = "str"
2582    if (c.length != 0) {}
2583    do {break} while (c.length != 0)
2584    while (c.length != 0) {break}
2585
2586    let d = new Object()
2587    if (d != null) {}
2588    do {break} while (d != null)
2589    while (d != null) {break}
2590
2591|CB_SEE|
2592~~~~~~~~
2593
2594* :ref:`R055`
2595* :ref:`R056`
2596* :ref:`R057`
2597* :ref:`R061`
2598* :ref:`R062`
2599* :ref:`R063`
2600* :ref:`R064`
2601* :ref:`R067`
2602* :ref:`R068`
2603
2604.. _R079:
2605
2606|CB_R| #79: Type annotation in catch clause is not supported
2607------------------------------------------------------------
2608
2609|CB_RULE|
2610~~~~~~~~~
2611
2612In |TS| catch clause variable type annotation must be ``any`` or ``unknown`` if specified. 
2613As |LANG| does not support these types, a type annotation should be omitted.
2614
2615|CB_BAD|
2616~~~~~~~~
2617
2618.. code-block:: typescript
2619
2620    try { 
2621        // some code
2622    }
2623    catch (a: unknown) {}
2624
2625|CB_OK|
2626~~~~~~~
2627
2628.. code:: typescript
2629
2630    try { 
2631        // some code
2632    }
2633    catch (a) {}
2634
2635|CB_SEE|
2636~~~~~~~~
2637
2638* :ref:`R087`
2639
2640.. _R080:
2641
2642|CB_R| #80: ``for .. in`` is not supported
2643------------------------------------------
2644
2645|CB_RULE|
2646~~~~~~~~~
2647
2648|LANG| does not support the iteration over object contents by the
2649``for .. in`` loop. For objects, iteration over properties at runtime is
2650considered redundant because object layout is known at compile time and cannot
2651change at runtime. For arrays, you can iterate with the regular ``for`` loop.
2652
2653|CB_BAD|
2654~~~~~~~~
2655
2656.. code-block:: typescript
2657
2658    let a: number[] = [1.0, 2.0, 3.0]
2659    for (let i in a) {
2660        console.log(a[i])
2661    }
2662
2663|CB_OK|
2664~~~~~~~
2665
2666.. code:: typescript
2667
2668    let a: number[] = [1.0, 2.0, 3.0]
2669    for (let i = 0; i < a.length; ++i) {
2670        console.log(a[i])
2671    }
2672
2673|CB_SEE|
2674~~~~~~~~
2675
2676* :ref:`R081`
2677* :ref:`R082`
2678
2679.. _R081:
2680
2681|CB_R| #81: Iterable interfaces are not supported
2682-------------------------------------------------
2683
2684|CB_RULE|
2685~~~~~~~~~
2686
2687|LANG| does not support the ``Symbol`` API, ``Symbol.iterator`` and
2688eventually iterable interfaces. Use arrays and library-level containers to
2689iterate over data.
2690
2691|CB_SEE|
2692~~~~~~~~
2693
2694* :ref:`R002`
2695* :ref:`R080`
2696* :ref:`R082`
2697
2698.. _R082:
2699
2700|CB_R| ``for-of`` is supported only for arrays, strings, sets, maps and classes derived from them
2701-------------------------------------------------------------------------------------------------
2702
2703|CB_RULE|
2704~~~~~~~~~
2705
2706|LANG| supports the iteration over arrays, strings, sets, maps and classes
2707derived from them by the ``for .. of`` loop, but does not support the
2708iteration of objects content. All typed arrays from the standard
2709library (for example, ``Int32Array``) are also supported.
2710
2711|CB_BAD|
2712~~~~~~~~
2713
2714.. code-block:: typescript
2715    class A {
2716        prop1: number;
2717        prop2: number;
2718    }
2719    let a = new A()
2720    for (let prop of a) {
2721        console.log(prop)
2722    }
2723
2724|CB_OK|
2725~~~~~~~
2726
2727.. code-block:: typescript
2728
2729    let a = new Set<number>([1, 2, 3])
2730    for (let n of a) {
2731        console.log(n)
2732    }
2733|CB_SEE|
2734~~~~~~~~
2735
2736* :ref:`R080`
2737* :ref:`R081`
2738
2739.. _R083:
2740
2741|CB_R| #83: Mapped type expression is not supported
2742---------------------------------------------------
2743
2744|CB_RULE|
2745~~~~~~~~~
2746
2747|LANG| does not support mapped types. Use other language idioms and regular classes
2748to achieve the same behaviour.
2749
2750|CB_BAD|
2751~~~~~~~~
2752
2753.. code-block:: typescript
2754
2755   type OptionsFlags<Type> = {
2756       [Property in keyof Type]: boolean;
2757   }
2758
2759.. _R084:
2760
2761|CB_R| #84: ``with`` statement is not supported
2762-----------------------------------------------
2763
2764|CB_RULE|
2765~~~~~~~~~
2766
2767|LANG| does not support the ``with`` statement. Use other language idioms
2768(including fully qualified names of functions) to achieve the same behaviour.
2769
2770.. _R085:
2771
2772|CB_R| #85: Values computed at runtime are not supported in ``case`` statements
2773-------------------------------------------------------------------------------
2774
2775|CB_RULE|
2776~~~~~~~~~
2777
2778|LANG| supports ``case`` statements that contain only compile-time values.
2779Use ``if`` statements as an alternative.
2780
2781|CB_BAD|
2782~~~~~~~~
2783
2784.. code-block:: typescript
2785
2786    let x = 2
2787    let y = 3
2788    switch (x) {
2789        case 1:
2790            console.log(1)
2791            break
2792        case 2:
2793            console.log(2)
2794            break
2795        case y:
2796            console.log(y)
2797            break
2798        default:
2799            console.log("other")
2800    }
2801
2802|CB_OK|
2803~~~~~~~
2804
2805.. code-block:: typescript
2806
2807    let x = 2
2808    switch (x) {
2809        case 1:
2810            console.log(1)
2811            break
2812        case 2:
2813            console.log(2)
2814            break
2815        case 3:
2816            console.log(3)
2817            break
2818        default:
2819            console.log("other")
2820    }
2821
2822|CB_SEE|
2823~~~~~~~~
2824
2825* :ref:`R112`
2826
2827.. _R086:
2828
2829|CB_R| #86: ``switch`` statements cannot accept values of arbitrary types
2830-------------------------------------------------------------------------
2831
2832|CB_RULE|
2833~~~~~~~~~
2834
2835|LANG| supports the values of the types ``char``, ``byte``, ``short``, ``int``,
2836``long``, ``Char``, ``Byte``, ``Short``, ``Int``, ``Long``, ``String`` or
2837``enum`` in ``switch`` statements. Use ``if`` statements in other cases.
2838
2839|CB_BAD|
2840~~~~~~~~
2841
2842.. code-block:: typescript
2843
2844    class Point {
2845        x: number = 0
2846        y: number = 0
2847    }
2848
2849    let a = new Point()
2850
2851    switch (a) {
2852        case null: break;
2853        default: console.log("not null")
2854    }
2855
2856|CB_OK|
2857~~~~~~~
2858
2859.. code-block:: typescript
2860
2861    class Point {
2862        x: number = 0
2863        y: number = 0
2864    }
2865
2866    let a = new Point()
2867
2868    if (a != null) {
2869        console.log("not null")
2870    }
2871
2872.. _R087:
2873
2874|CB_R| #87: ``throw`` statements cannot accept values of arbitrary types
2875------------------------------------------------------------------------
2876
2877|CB_RULE|
2878~~~~~~~~~
2879
2880|LANG| supports throwing only objects of the class ``Error`` or any
2881derived class. Throwing an arbitrary type (i.e., a ``number`` or ``string``)
2882is prohibited.
2883
2884|CB_BAD|
2885~~~~~~~~
2886
2887.. code-block:: typescript
2888
2889    throw 4
2890    throw ""
2891    throw new Error()
2892
2893|CB_OK|
2894~~~~~~~
2895
2896.. code-block:: typescript
2897
2898    throw new Error()
2899
2900.. _R088:
2901
2902|CB_R| #88: Each overloaded function should have its body
2903---------------------------------------------------------
2904
2905|CB_RULE|
2906~~~~~~~~~
2907
2908|LANG| does not support the |TS| style of overloading signatures with one
2909function body. Define each overloading function with its own body instead of
2910one body for a list of signatures.
2911
2912|CB_BAD|
2913~~~~~~~~
2914
2915.. code:: typescript
2916
2917    function add(x: number, y: number): number
2918    function add(x: string, y: string): string
2919    function add(x: any, y: any): any {
2920        return x + y
2921    }
2922
2923    console.log(add(2, 3)) // returns 5
2924    console.log(add("hello", "world")) // returns "helloworld"
2925
2926|CB_OK|
2927~~~~~~~
2928
2929.. code:: typescript
2930
2931    function add(x: number, y: number): number {
2932        return x + y
2933    }
2934
2935    function add(x: string, y: string): string {
2936        return x + y
2937    }
2938
2939    function main() {
2940        console.log(add(2, 3)) // returns 5
2941        console.log(add("hello", "world")) // returns "helloworld"
2942    }
2943
2944|CB_SEE|
2945~~~~~~~~
2946
2947* :ref:`R089`
2948
2949.. _R089:
2950
2951|CB_R| #89: Each overloaded function with optional parameters should have its body
2952----------------------------------------------------------------------------------
2953
2954|CB_RULE|
2955~~~~~~~~~
2956
2957|LANG| does not support the |TS| style of overloading signatures with one
2958function body. Write a separate body for each overloaded signature instead of
2959an optional parameter like `value?` for a single body in |TS|.
2960
2961|CB_BAD|
2962~~~~~~~~
2963
2964.. code:: typescript
2965
2966    function foo(name: string): number
2967    function foo(name: string, value: string): Accessor
2968    function foo(name: any, value?: string): any {
2969        // one body here
2970    }
2971
2972|CB_OK|
2973~~~~~~~
2974
2975.. code:: typescript
2976
2977    function foo(name: string): string {
2978        return name
2979    }
2980
2981    function foo(name: string, value: string): Accessor {
2982        return new Accessor()
2983    }
2984
2985|CB_SEE|
2986~~~~~~~~
2987
2988* :ref:`R088`
2989
2990.. _R090:
2991
2992|CB_R| #90: Function must have explicit return type
2993---------------------------------------------------
2994
2995|CB_RULE|
2996~~~~~~~~~
2997
2998|LANG| requires all functions to have explicit return types. For corner cases,
2999use `Object` when it is difficult to determine the return type.
3000
3001|CB_BAD|
3002~~~~~~~~
3003
3004.. code-block:: typescript
3005
3006    function f(x: number) {
3007        if (x <= 0) {
3008            return x
3009        }
3010        return g(x)
3011    }
3012
3013    function g(x: number) {
3014        return f(x - 1)
3015    }
3016
3017    function doOperation(x: number, y: number) {
3018        return x + y
3019    }
3020
3021    console.log(f(10))
3022    console.log(doOperation(2, 3))
3023
3024|CB_OK|
3025~~~~~~~
3026
3027.. code-block:: typescript
3028
3029    function f(x: number): Object {
3030        if (x <= 0) {
3031            return x
3032        }
3033        return g(x)
3034    }
3035
3036    function g(x: number): Object {
3037        return f(x - 1)
3038    }
3039
3040    function doOperation(x: number, y: number): Object {
3041        let z = x + y
3042        return z
3043    }
3044
3045    function main(): void {
3046        console.log(f(-10) as number) // returns -10
3047        console.log(doOperation(2, 3)) // returns 5
3048    }
3049
3050|CB_R| #91: Destructuring parameter declarations are not supported
3051------------------------------------------------------------------
3052
3053|CB_RULE|
3054~~~~~~~~~
3055
3056|LANG| requires that parameters must be passed directly to the function, and
3057local names must be assigned manually.
3058
3059|CB_BAD|
3060~~~~~~~~
3061
3062.. code:: typescript
3063
3064    function drawText({ text = "", location: [x, y] = [0, 0], bold = false }) {
3065        console.log(text)
3066        console.log(x)
3067        console.log(y)
3068        console.log(bold)
3069    }
3070
3071    drawText({ text: "Hello, world!", location: [100, 50], bold: true })
3072
3073|CB_OK|
3074~~~~~~~
3075
3076.. code:: typescript
3077
3078    function drawText(text: String, location: number[], bold: boolean) {
3079        let x = location[0]
3080        let y = location[1]
3081        console.log(text)
3082        console.log(x)
3083        console.log(y)
3084        console.log(bold)
3085    }
3086
3087    function main() {
3088        drawText("Hello, world!", [100, 50], true)
3089    }
3090
3091.. _R092:
3092
3093|CB_R| #92: Nested functions are not supported
3094----------------------------------------------
3095
3096|CB_RULE|
3097~~~~~~~~~
3098
3099|LANG| does not support nested functions. Use lambdas instead.
3100
3101|CB_BAD|
3102~~~~~~~~
3103
3104.. code-block:: typescript
3105
3106    function addNum(a: number, b: number): void {
3107
3108        // nested function:
3109        function logToConsole(message: String): void {
3110            console.log(message)
3111        }
3112
3113        let result = a + b
3114
3115        // Invoking the nested function:
3116        logToConsole("result is " + result)
3117    }
3118
3119|CB_OK|
3120~~~~~~~
3121
3122.. code-block:: typescript
3123
3124    function addNum(a: number, b: number): void {
3125
3126        // Use lambda instead of a nested function:
3127        let logToConsole: (message: String): void = (message: String): void => {
3128            console.println(message)
3129        }
3130
3131        let result = a + b
3132
3133        logToConsole("result is " + result)
3134    }
3135
3136.. _R093:
3137
3138|CB_R| #93: Using ``this`` inside stand-alone functions is not supported
3139------------------------------------------------------------------------
3140
3141|CB_RULE|
3142~~~~~~~~~
3143
3144|LANG| does not support the usage of ``this`` inside stand-alone functions.
3145``this`` can be used in methods only.
3146
3147|CB_BAD|
3148~~~~~~~~
3149
3150.. code-block:: typescript
3151
3152    function foo(i: number) {
3153        this.count = i
3154    }
3155
3156    class A {
3157        count: number = 1
3158        m = foo
3159    }
3160
3161    let a = new A()
3162    console.log(a.count) // prints "1"
3163    a.m(2)
3164    console.log(a.count) // prints "2"
3165
3166
3167|CB_OK|
3168~~~~~~~
3169
3170.. code-block:: typescript
3171
3172    class A {
3173        count: number = 1
3174        m(i: number): void {
3175            this.count = i
3176        }
3177    }
3178
3179    function main(): void {
3180        let a = new A()
3181        console.log(a.count)  // prints "1"
3182        a.m(2)
3183        console.log(a.count)  // prints "2"
3184    }
3185
3186.. _R094:
3187
3188|CB_R| #94: Generator functions are not supported
3189-------------------------------------------------
3190
3191|CB_RULE|
3192~~~~~~~~~
3193
3194Currently, |LANG| does not support generator functions.
3195Use the ``async`` / ``await`` mechanism for multitasking.
3196
3197|CB_BAD|
3198~~~~~~~~
3199
3200.. code-block:: typescript
3201
3202    function* counter(start: number, end: number) {
3203        for (let i = start; i <= end; i++) {
3204            yield i
3205        }
3206    }
3207
3208    for (let num of counter(1, 5)) {
3209        console.log(num)
3210    }
3211
3212|CB_OK|
3213~~~~~~~
3214
3215.. code-block:: typescript
3216
3217    for (let i = 1; i <= 5; ++i) {
3218        console.log(i)
3219    }
3220
3221.. _R095:
3222
3223|CB_R| #95: Asynchronous functions are partially supported
3224----------------------------------------------------------
3225
3226|CB_RULE|
3227~~~~~~~~~
3228
3229|LANG| partially supports asynchronous functions.
3230Using the ``launch`` mechanism (|LANG| extension to |TS|)
3231is recommended for multitasking.
3232
3233|CB_BAD|
3234~~~~~~~~
3235
3236.. code-block:: typescript
3237
3238    async function sum(numbers: number[]): Promise<number> {
3239        let sum = 0
3240        for (let num of numbers) {
3241            sum += await num
3242        }
3243        return sum
3244    }
3245
3246    ...
3247    const result = await sum(5, 10)
3248    ...
3249
3250|CB_OK|
3251~~~~~~~
3252
3253.. code-block:: typescript
3254
3255    function sum(numbers: number[]): number {
3256        let sum = 0
3257        for (let i = 0; i < numbers.length; ++i) {
3258            sum += numbers[i]
3259        }
3260        return sum
3261    }
3262
3263    ...
3264    const result = launch sum(5, 10)  // `result` will be of type `Promise<number>`
3265    ...
3266
3267NOT recommended:
3268
3269.. code-block:: typescript
3270
3271    async function sum(numbers: number[]): Promise<number> {
3272        let sum = 0
3273        for (let i = 0; i < numbers.length; ++i) {
3274            sum += await numbers[i]
3275        }
3276        return sum
3277    }
3278
3279    ...
3280    const result = sum(5, 10)
3281    ...
3282
3283.. _R096:
3284
3285|CB_R| #96: Type guarding is supported with ``instanceof`` and ``as``
3286---------------------------------------------------------------------
3287
3288|CB_RULE|
3289~~~~~~~~~
3290
3291|LANG| does not support the ``is`` operator, which must be replaced by the
3292``instanceof`` operator. Note that the fields of an object must be cast to the
3293appropriate type with the ``as`` operator before use.
3294
3295|CB_BAD|
3296~~~~~~~~
3297
3298.. code-block:: typescript
3299
3300    class Foo {
3301        foo: number = 0
3302        common: string = ""
3303    }
3304
3305    class Bar {
3306        bar: number = 0
3307        common: string = ""
3308    }
3309
3310    function isFoo(arg: any): arg is Foo {
3311        return arg.foo !== undefined
3312    }
3313
3314    function doStuff(arg: Foo | Bar) {
3315        if (isFoo(arg)) {
3316            console.log(arg.foo)    // OK
3317            console.log(arg.bar)    // Error!
3318        }
3319        else {
3320            console.log(arg.foo)    // Error!
3321            console.log(arg.bar)    // OK
3322        }
3323    }
3324
3325    doStuff({ foo: 123, common: '123' })
3326    doStuff({ bar: 123, common: '123' })
3327
3328|CB_OK|
3329~~~~~~~
3330
3331.. code-block:: typescript
3332
3333    class Foo {
3334        foo: number = 0
3335        common: string = ""
3336    }
3337
3338    class Bar {
3339        bar: number = 0
3340        common: string = ""
3341    }
3342
3343    function isFoo(arg: Object): boolean {
3344        return arg instanceof Foo
3345    }
3346
3347    function doStuff(arg: Object): void {
3348        if (isFoo(arg)) {
3349            let fooArg = arg as Foo
3350            console.log(fooArg.foo)     // OK
3351            console.log(arg.bar)        // Error!
3352        }
3353        else {
3354            let barArg = arg as Bar
3355            console.log(arg.foo)        // Error!
3356            console.log(barArg.bar)     // OK
3357        }
3358    }
3359
3360    function main(): void {
3361        doStuff(new Foo())
3362        doStuff(new Bar())
3363    }
3364
3365.. _R098:
3366
3367|CB_R| #98: Spreading an array into function arguments is not supported
3368-----------------------------------------------------------------------
3369
3370|CB_RULE|
3371~~~~~~~~~
3372
3373|LANG| does not support the spread operator.
3374"Unpack" data from an array to a callee manually.
3375
3376|CB_BAD|
3377~~~~~~~~
3378
3379.. code-block:: typescript
3380
3381    function foo(x, y, z) {}
3382
3383    let args = [0, 1, 2]
3384    foo(...args)
3385
3386|CB_OK|
3387~~~~~~~
3388
3389.. code-block:: typescript
3390
3391    function foo(x: number, y: number, z: number): void {}
3392
3393    function main(): void {
3394        let args: number[] = [0, 1, 2]
3395        foo(args[0], args[1], args[2])
3396    }
3397
3398.. _R099:
3399
3400|CB_R| #99: Spread operator is not supported
3401--------------------------------------------
3402
3403|CB_RULE|
3404~~~~~~~~~
3405
3406|LANG| does not support the spread operator.
3407"Unpack" data from arrays indices manually where necessary.
3408
3409|CB_BAD|
3410~~~~~~~~
3411
3412.. code-block:: typescript
3413
3414    let list = [1, 2]
3415    list = [...list, 3, 4]
3416
3417|CB_OK|
3418~~~~~~~
3419
3420.. code-block:: typescript
3421
3422    let list: number[] = [1, 2]
3423    list = [list[0], list[1], 3, 4]
3424
3425.. _R100:
3426
3427|CB_R| #100: Spreading an object is not supported
3428---------------------------------------------------
3429
3430|CB_RULE|
3431~~~~~~~~~
3432
3433|LANG| does not support the spread operator.
3434"Unpack" data from an object to a callee manually, field by field.
3435
3436|CB_BAD|
3437~~~~~~~~
3438
3439.. code-block:: typescript
3440
3441    const point2d = {x: 1, y: 2}
3442    const point3d = {...point2d, z: 3}
3443
3444|CB_OK|
3445~~~~~~~
3446
3447.. code-block:: typescript
3448
3449    class Point2D {
3450        x: number
3451        y: number
3452
3453        constructor(x: number, y: number) {
3454            this.x = x
3455            this.y = y
3456        }
3457    }
3458
3459    class Point3D {
3460        x: number
3461        y: number
3462        z: number
3463
3464        constructor(x: number, y: number, z: number) {
3465            this.x = x
3466            this.y = y
3467            this.z = z
3468        }
3469    }
3470
3471    function main(): void {
3472        const point2d = new Point2D(1, 2)
3473        const point3d = new Point3D(point2d.x, point2d.y, 3)
3474    }
3475
3476|CB_R| #101: Interfaces with optional properties and call signatures are not supported
3477--------------------------------------------------------------------------------------
3478
3479|CB_RULE|
3480~~~~~~~~~
3481
3482|LANG| does not support interfaces with optional properties and interfaces
3483with call signatures.
3484
3485|CB_BAD|
3486~~~~~~~~
3487
3488.. code:: typescript
3489
3490    // Interface with optional properties
3491    interface Person {
3492      firstName: string
3493      lastName: string
3494      age?: number
3495    }
3496
3497    // Interface with call signature
3498    interface Greet {
3499      (name: string): string
3500    }
3501
3502|CB_OK|
3503~~~~~~~
3504
3505.. code:: typescript
3506
3507    // Use nullable type instead of optional property
3508    interface Person {
3509      firstName: string
3510      lastName: string
3511      age: number | null
3512    }
3513
3514    // Use a method signature instead of call signature
3515    interface Greet {
3516      action (name: string): string
3517    }
3518
3519
3520
3521|CB_R| #102: Interface declarations (extends same property)
3522-----------------------------------------------------------
3523
3524|CB_RULE|
3525~~~~~~~~~
3526
3527|LANG| does not allow an interface to contain two methods with signatures that
3528are  not distinguishable, e.g., two methods that have the same parameter lists
3529but different return types.
3530
3531|CB_BAD|
3532~~~~~~~~
3533
3534.. code:: typescript
3535
3536    interface Mover {
3537        getStatus(): { speed: number }
3538    }
3539    interface Shaker {
3540        getStatus(): { frequency: number }
3541    }
3542
3543    interface MoverShaker extends Mover, Shaker {
3544        getStatus(): { speed: number; frequency: number }
3545    }
3546
3547    class C implements MoverShaker {
3548        private speed: number = 0
3549        private frequency: number = 0
3550
3551        getStatus() {
3552            return { speed: this.speed, frequency: this.frequency }
3553        }
3554    }
3555
3556In |TS|, an interface that extends ``Mover`` and ``Shaker`` must declare a
3557new ``getStatus`` with a combined result type. It is not allowed in |LANG|.
3558
3559.. _R103:
3560
3561|CB_R| #103: Declaration merging is not supported
3562-------------------------------------------------
3563
3564|CB_RULE|
3565~~~~~~~~~
3566
3567|LANG| does not support merging declratations. All definitions of classes,
3568interfaces and so on must be kept compact in the code base.
3569
3570|CB_BAD|
3571~~~~~~~~
3572
3573.. code-block:: typescript
3574
3575    interface Document {
3576        createElement(tagName: any): Element
3577    }
3578
3579    interface Document {
3580        createElement(tagName: string): HTMLElement
3581    }
3582
3583    interface Document {
3584        createElement(tagName: number): HTMLDivElement
3585        createElement(tagName: boolean): HTMLSpanElement
3586        createElement(tagName: string, value: number): HTMLCanvasElement
3587    }
3588
3589|CB_OK|
3590~~~~~~~
3591
3592.. code-block:: typescript
3593
3594    interface Document {
3595        createElement(tagName: number): HTMLDivElement
3596        createElement(tagName: boolean): HTMLSpanElement
3597        createElement(tagName: string, value: number): HTMLCanvasElement
3598        createElement(tagName: string): HTMLElement
3599        createElement(tagName: Object): Element
3600    }
3601
3602.. _R104:
3603
3604|CB_R| #104: Interfaces cannot extend classes
3605---------------------------------------------
3606
3607|CB_RULE|
3608~~~~~~~~~
3609
3610|LANG| does not support interfaces that extend classes. Interfaces can extend
3611only interfaces.
3612
3613|CB_BAD|
3614~~~~~~~~
3615
3616.. code-block:: typescript
3617
3618    class Control {
3619        state: number = 0
3620    }
3621
3622    interface SelectableControl extends Control {
3623        select(): void
3624    }
3625
3626|CB_OK|
3627~~~~~~~
3628
3629.. code-block:: typescript
3630
3631    interface Control {
3632        state: number = 0
3633    }
3634
3635    interface SelectableControl extends Control {
3636        select(): void
3637    }
3638
3639.. _R105:
3640
3641|CB_R| #105: Property-based runtime type checks are not supported
3642-----------------------------------------------------------------
3643
3644|CB_RULE|
3645~~~~~~~~~
3646
3647|LANG| requires that object layout is determined in compile-time and cannot
3648be changed at runtime. There for no runtime property-based checks are supported.
3649If you need to do a type cast, use ``as`` operator and use desired properties
3650and methods. If some property doesn't exist then an attempt to reference it
3651will result in a compile-time error.
3652
3653|CB_BAD|
3654~~~~~~~~
3655
3656.. code-block:: typescript
3657
3658    class A {
3659        foo() {}
3660        bar() {}
3661    }
3662
3663    function getSomeObject() {
3664        return new A()
3665    }
3666
3667    let obj: any = getSomeObject()
3668    if (obj && obj.foo && obj.bar) {
3669        console.log("Yes")  // prints "Yes" in this example
3670    } else {
3671        console.log("No")
3672    }
3673
3674|CB_OK|
3675~~~~~~~
3676
3677.. code-block:: typescript
3678
3679    class A {
3680        foo(): void {}
3681        bar(): void {}
3682    }
3683
3684    function getSomeObject(): A {
3685        return new A()
3686    }
3687
3688    function main(): void {
3689        let tmp: Object = getSomeObject()
3690        let obj: A = tmp as A
3691        obj.foo()       // OK
3692        obj.bar()       // OK
3693        obj.some_foo()  // Compile-time error: Method some_foo does not exist on this type
3694    }
3695
3696|CB_SEE|
3697~~~~~~~~
3698
3699* :ref:`R001`
3700* :ref:`R002`
3701* :ref:`R052`
3702* :ref:`R059`
3703* :ref:`R060`
3704* :ref:`R066`
3705* :ref:`R109`
3706
3707.. _R106:
3708
3709|CB_R| #106: Constructor function type is not supported
3710-------------------------------------------------------
3711
3712|CB_RULE|
3713~~~~~~~~~
3714
3715|LANG| does not support the usage of the constructor function type.
3716Use lambdas instead, as they can be generalized to several types of objects.
3717
3718|CB_BAD|
3719~~~~~~~~
3720
3721.. code-block:: typescript
3722
3723    class Person {
3724        constructor(
3725            name: string,
3726            age: number
3727        ) {}
3728    }
3729
3730    type PersonConstructor = new (name: string, age: number) => Person
3731
3732    function createPerson(Ctor: PersonConstructor, name: string, age: number): Person {
3733        return new Ctor(name, age)
3734    }
3735
3736    const person = createPerson(Person, 'John', 30)
3737
3738|CB_OK|
3739~~~~~~~
3740
3741.. code-block:: typescript
3742
3743    class Person {
3744        constructor(
3745            name: string,
3746            age: number
3747        ) {}
3748    }
3749
3750    let PersonConstructor: (name: string, age: number): Person = (name: string, age: number): Person => {
3751        return new Person(name, age)
3752    }
3753
3754    function createPerson(Ctor: (name: string, age: number): Person, name: string, age: number): Person {
3755        return PersonConstructor(name, age)
3756    }
3757
3758    function main(): void {
3759        const person = createPerson(PersonConstructor, "John", 30)
3760    }
3761
3762.. _R107:
3763
3764|CB_R| #107: Constructor declarations
3765-------------------------------------
3766
3767|CB_RULE|
3768~~~~~~~~~
3769
3770|LANG| does not support optional parameters in constructors.
3771Constructors are not inherited from a superclass to a subclass. Use overloading
3772constructors instead of constructors with optional parameters:
3773
3774|CB_BAD|
3775~~~~~~~~
3776
3777.. code:: typescript
3778
3779    class Foo {
3780      constructor(bar: string = 'default', baz?: number) {}
3781    }
3782
3783|CB_OK|
3784~~~~~~~
3785
3786.. code:: typescript
3787
3788    class Foo {
3789        constructor(bar: string) {}
3790        constructor(bar: string, baz: number) {}
3791    }
3792
3793|CB_RULE|
3794~~~~~~~~~
3795
3796In |LANG|, constructors are not inherited from a superclass.
3797
3798|CB_BAD|
3799~~~~~~~~
3800
3801The constructor defined in a superclass can be used in a subclass.
3802
3803.. code:: typescript
3804
3805    class C1 {
3806        constructor(bar: string, baz: number) {}
3807    }
3808    class C2 extends Foo {}
3809
3810    let c = C2("a", "b")
3811
3812|CB_OK|
3813~~~~~~~
3814
3815A subclass must define its own constructor.
3816
3817.. code:: typescript
3818
3819    class C1 {
3820        constructor(bar: string, baz: number) {}
3821    }
3822    class C2 extends Foo {
3823        constructor(bar: string, baz: number) {
3824            super(bar, string)
3825        }
3826    }
3827
3828    let c = C2("a", "b")
3829
3830|CB_SEE|
3831~~~~~~~~
3832
3833* :ref:`R015`
3834
3835.. _R108:
3836
3837|CB_R| #108: Overloaded constructors with shared body are not supported
3838-----------------------------------------------------------------------
3839
3840|CB_RULE|
3841~~~~~~~~~
3842
3843|LANG| does not support sharing a body between function overloads.
3844The shared body feature for ``constructor`` is not supported, either.
3845Overload constructor with a separate body for each signature.
3846
3847|CB_BAD|
3848~~~~~~~~
3849
3850.. code-block:: typescript
3851
3852    class Person {
3853        name: string
3854        age: number
3855
3856        constructor(name: string, age?: number) {
3857            this.name = name
3858            if (age) {
3859                this.age = age
3860            } else {
3861                this.age = 0
3862            }
3863        }
3864    }
3865
3866|CB_OK|
3867~~~~~~~
3868
3869.. code-block:: typescript
3870
3871    class Person {
3872        name: string
3873        age: number
3874
3875        constructor(name: string, age: number) {
3876            this.name = name
3877            this.age = age
3878        }
3879
3880        constructor(name: string) {
3881            this.name = name
3882            this.age = 0
3883        }
3884    }
3885
3886.. _R109:
3887
3888|CB_R| #109: Dynamic property declaration is not supported
3889----------------------------------------------------------
3890
3891|CB_RULE|
3892~~~~~~~~~
3893
3894|LANG| does not support dynamic property declaration. All object properties must
3895be declared immediately in the class. While it can be replaced with an array
3896of objects, it is still better to adhere to the static language paradigm and
3897declare fields, their names and types explicitly.
3898
3899|CB_BAD|
3900~~~~~~~~
3901
3902.. code-block:: typescript
3903
3904    class Person {
3905        name: string = ""
3906        age: number = 0
3907        [key: string]: string | number
3908    }
3909
3910    const person: Person = {
3911        name: "John",
3912        age: 30,
3913        email: "john@example.com",
3914        phone: 1234567890,
3915    }
3916
3917|CB_OK|
3918~~~~~~~
3919
3920.. code-block:: typescript
3921
3922    class Person {
3923        name: string
3924        age: number
3925        email: string
3926        phone: number
3927
3928        constructor(name: string, age: number, email: string, phone: number) {
3929            this.name = name
3930            this.age = age
3931            this.email = email
3932            this.phone = phone
3933        }
3934    }
3935
3936    function main(): void {
3937        const person: Person = new Person("John", 30, "john@example.com", 1234567890)
3938    }
3939
3940|CB_SEE|
3941~~~~~~~~
3942
3943* :ref:`R001`
3944* :ref:`R002`
3945* :ref:`R052`
3946* :ref:`R059`
3947* :ref:`R060`
3948* :ref:`R066`
3949* :ref:`R105`
3950
3951.. _R111:
3952
3953|CB_R| #111: Explicit values for enumeration constants are not supported
3954------------------------------------------------------------------------
3955
3956|CB_RULE|
3957~~~~~~~~~
3958
3959Currently, |LANG| does not support assigning explicit values for ``enums``.
3960
3961|CB_BAD|
3962~~~~~~~~
3963
3964.. code-block:: typescript
3965
3966    enum E {
3967        A,
3968        B,
3969        C = 10,
3970        D
3971    }
3972
3973|CB_OK|
3974~~~~~~~
3975
3976.. code-block:: typescript
3977
3978    enum E {
3979        A,
3980        B,
3981        C = 10,  // Compile-time error: assigning out of order values for enums is not supported
3982        D
3983    }
3984
3985    enum E_fixed {
3986        A,
3987        B,
3988        C,   // OK
3989        D
3990    }
3991
3992.. _R112:
3993
3994.. _R113:
3995
3996|CB_R| #113: ``enum`` declaration merging is not supported
3997----------------------------------------------------------
3998
3999|CB_RULE|
4000~~~~~~~~~
4001
4002|LANG| does not support merging declratations for ``enum``.
4003The declaration of each ``enum`` must be kept compact in the code base.
4004
4005|CB_BAD|
4006~~~~~~~~
4007
4008.. code:: typescript
4009
4010    enum Color {
4011        RED,
4012        GREEN
4013    }
4014    enum Color {
4015        YELLOW
4016    }
4017    enum Color {
4018        BLACK,
4019        BLUE
4020    }
4021
4022|CB_OK|
4023~~~~~~~
4024
4025.. code:: typescript
4026
4027    enum Color {
4028        RED,
4029        GREEN,
4030        YELLOW,
4031        BLACK,
4032        BLUE
4033    }
4034
4035.. _R114:
4036
4037|CB_R| #114: Namespaces cannot be used as objects
4038-------------------------------------------------
4039
4040|CB_RULE|
4041~~~~~~~~~
4042
4043|LANG| does not support the usage of namespaces as objects.
4044Classes or modules can be interpreted as analogues of namespaces.
4045
4046|CB_BAD|
4047~~~~~~~~
4048
4049.. code-block:: typescript
4050
4051    namespace MyNamespace {
4052        export let x: number
4053    }
4054
4055    let m = MyNamespace
4056    m.x = 2
4057
4058|CB_OK|
4059~~~~~~~
4060
4061.. code-block:: typescript
4062
4063    namespace MyNamespace {
4064        export let x: number
4065    }
4066
4067    MyNamespace.x = 2
4068
4069.. _R115:
4070
4071|CB_R| #115: Scripts and modules
4072--------------------------------
4073
4074|CB_RULE|
4075~~~~~~~~~
4076
4077In general, scripts and modules in |LANG| are very close to |TS|.
4078Differences are described in separate recipes.
4079
4080|CB_SEE|
4081~~~~~~~~
4082
4083* :ref:`R117`
4084* :ref:`R118`
4085* :ref:`R119`
4086* :ref:`R120`
4087* :ref:`R121`
4088* :ref:`R122`
4089* :ref:`R124`
4090* :ref:`R125`
4091* :ref:`R126`
4092
4093.. _R116:
4094
4095|CB_R| #116: Non-declaration statements in namespaces are not supported
4096-----------------------------------------------------------------------
4097
4098|CB_RULE|
4099~~~~~~~~~
4100
4101|LANG| does not support statements in namespaces. Use a function to exectute statements.
4102
4103|CB_BAD|
4104~~~~~~~~~
4105
4106.. code:: typescript
4107
4108    namespace A {
4109        export let x: number
4110        x = 1
4111    }
4112
4113|CB_OK|
4114~~~~~~~~~
4115
4116Initialization function should be called to execute statements.
4117
4118.. code:: typescript
4119
4120    namespace A {
4121        export let x: number
4122
4123        export function init() {
4124          x = 1
4125        }
4126    }
4127    A.init()
4128
4129
4130.. _R117:
4131
4132|CB_R| #117: Statement as top-level element
4133-------------------------------------------
4134
4135|CB_RULE|
4136~~~~~~~~~
4137
4138|LANG| does not support statements as top-level elements. Statements must be
4139placed in a block ``{}``.
4140
4141|CB_BAD|
4142~~~~~~~~~
4143
4144.. code:: typescript
4145
4146    let a = 1
4147    let b = 2
4148    if (b == a) {
4149        console.log("a EQ b")
4150    } else {
4151        console.log("a NEQ b")
4152    }
4153
4154|CB_OK|
4155~~~~~~~~~
4156
4157.. code:: typescript
4158
4159    // A block can be a top-level element,
4160    // put statements inside one or several blocks:
4161    {
4162        let a = 1
4163        let b = 2
4164    }
4165
4166    {
4167        if (b == a) {
4168            console.log("a EQ b")
4169        } else {
4170            console.log("a NEQ b")
4171        }
4172    }
4173
4174
4175.. _R118:
4176
4177|CB_R| #118: Special import type declarations are not supported
4178---------------------------------------------------------------
4179
4180|CB_RULE|
4181~~~~~~~~~
4182
4183|LANG| does not have a special notation for importing types.
4184Use ordinary import instead.
4185
4186|CB_BAD|
4187~~~~~~~~
4188
4189.. code:: typescript
4190
4191    // Re-using the same import
4192    import { APIResponseType } from "./api"
4193
4194    // Explicitly use import type
4195    import type { APIResponseType } from "./api"
4196
4197|CB_OK|
4198~~~~~~~
4199
4200.. code:: typescript
4201
4202    import { APIResponseType } from "./api"
4203
4204|CB_SEE|
4205~~~~~~~~
4206
4207* :ref:`R119`
4208* :ref:`R120`
4209* :ref:`R121`
4210
4211.. _R119:
4212
4213|CB_R| #119: Importing a module for side-effects only is not supported
4214----------------------------------------------------------------------
4215
4216|CB_RULE|
4217~~~~~~~~~
4218
4219|LANG| does not support global variables like ``window`` to avoid
4220side-effects during module importing. All variables marked as export can be
4221accessed through the ``*`` syntax.
4222
4223|CB_BAD|
4224~~~~~~~~
4225
4226.. code:: typescript
4227
4228    // === module at "path/to/module.ts"
4229    export const EXAMPLE_VALUE = 42
4230
4231    // Set a global variable
4232    window.MY_GLOBAL_VAR = "Hello, world!"
4233
4234    // ==== using this module:
4235    import "path/to/module"
4236
4237|CB_OK|
4238~~~~~~~
4239
4240.. code:: typescript
4241
4242    import * from "path/to/module"
4243
4244.. _R120:
4245
4246|CB_R| #120: ``import default as ...`` is not supported
4247-------------------------------------------------------
4248
4249|CB_RULE|
4250~~~~~~~~~
4251
4252|LANG| does not support ``import default as ...`` syntax.
4253Use explicit ``import ... from ...`` instead.
4254
4255|CB_BAD|
4256~~~~~~~~
4257
4258.. code-block:: typescript
4259
4260    import { default as d } from "mod"
4261
4262|CB_OK|
4263~~~~~~~
4264
4265.. code-block:: typescript
4266
4267    import d from "mod"
4268
4269|CB_SEE|
4270~~~~~~~~
4271
4272* :ref:`R122`
4273
4274.. _R121:
4275
4276|CB_R| #121: ``require`` is not supported
4277-----------------------------------------
4278
4279|CB_RULE|
4280~~~~~~~~~
4281
4282|LANG| does not support importing via ``require``. Use ``import`` instead.
4283
4284|CB_BAD|
4285~~~~~~~~
4286
4287.. code-block:: typescript
4288
4289    import m = require("mod")
4290
4291|CB_OK|
4292~~~~~~~
4293
4294.. code-block:: typescript
4295
4296    import * as m from "mod"
4297
4298.. _R122:
4299
4300|CB_R| #122: ``export default`` is not supported
4301------------------------------------------------
4302
4303|CB_RULE|
4304~~~~~~~~~
4305
4306|LANG| does not support ``export default``.
4307
4308|CB_BAD|
4309~~~~~~~~
4310
4311.. code-block:: typescript
4312
4313    // file1.ts
4314    export default class MyClass {
4315        // ...
4316    }
4317
4318    // file2.ts
4319    // Can write just `MyClass` instead of `{ MyClass }` in case of default export
4320    import MyClass from './file1'
4321
4322|CB_OK|
4323~~~~~~~
4324
4325.. code-block:: typescript
4326
4327    // module1
4328    export class MyClass {
4329        // ...
4330    }
4331
4332    // module2
4333    // Use explicit name in import
4334    import { MyClass } from "./module1"
4335
4336|CB_SEE|
4337~~~~~~~~
4338
4339* :ref:`R120`
4340
4341.. _R124:
4342
4343|CB_R| #124: Export list declaration is not supported
4344-----------------------------------------------------
4345
4346|CB_RULE|
4347~~~~~~~~~
4348
4349|LANG| does not support syntax of export list declarations. All exported
4350entities must be explicitly annotated with the ``export`` keyword.
4351
4352|CB_BAD|
4353~~~~~~~~
4354
4355.. code-block:: typescript
4356
4357    export { x }
4358    export { x } from "mod"
4359    export { x, y as b, z as c }
4360
4361|CB_OK|
4362~~~~~~~
4363
4364.. code-block:: typescript
4365
4366    let x = 1
4367    class MyClass {}
4368    export let y = x, z: number = 2
4369    export RenamedClass = MyClass
4370
4371|CB_SEE|
4372~~~~~~~~
4373
4374* :ref:`R125`
4375* :ref:`R126`
4376
4377.. _R125:
4378
4379|CB_R| #125: Re-exporting is not supported
4380------------------------------------------
4381
4382|CB_RULE|
4383~~~~~~~~~
4384
4385|LANG| does not support re-exporting. All desired entities must be
4386imported explicitly from the modules that export them.
4387
4388|CB_BAD|
4389~~~~~~~~
4390
4391.. code-block:: typescript
4392
4393    // module1
4394    export class MyClass {
4395        // ...
4396    }
4397
4398    // module2
4399    export { MyClass } from "module1"
4400
4401    // consumer module
4402    import { MyClass } from "module2"
4403
4404    const myInstance = new MyClass()
4405
4406|CB_OK|
4407~~~~~~~
4408
4409.. code-block:: typescript
4410
4411    // module1
4412    export class MyClass {
4413      // ...
4414    }
4415
4416    // module2
4417    // some stuff
4418
4419    // consumer module
4420    import MyClass from "module1"
4421    import * from "module2"
4422
4423    const myInstance = new MyClass()
4424
4425|CB_SEE|
4426~~~~~~~~
4427
4428* :ref:`R124`
4429* :ref:`R126`
4430
4431.. _R126:
4432
4433|CB_R| #126: ``export = ...`` assignment is not supported
4434---------------------------------------------------------
4435
4436|CB_RULE|
4437~~~~~~~~~
4438
4439|LANG| does not support ``export = ...`` syntax.
4440Use regular ``export`` / ``import`` instead.
4441
4442|CB_BAD|
4443~~~~~~~~
4444
4445.. code-block:: typescript
4446
4447    // module1
4448    export = Point
4449
4450    class Point {
4451        constructor(x: number, y: number) {}
4452        static origin = new Point(0, 0)
4453    }
4454
4455    // module2
4456    import Pt = require("module1")
4457
4458    let p = Pt.origin
4459
4460|CB_OK|
4461~~~~~~~
4462
4463.. code-block:: typescript
4464
4465    // module1
4466    export class Point {
4467        constructor(x: number, y: number) {}
4468        static origin = new Point(0, 0)
4469    }
4470
4471    // module2
4472    import * as Pt from "module1"
4473
4474    let p = Pt.origin
4475
4476|CB_SEE|
4477~~~~~~~~
4478
4479* :ref:`R124`
4480* :ref:`R125`
4481
4482
4483.. _R127:
4484
4485|CB_R| #127: Special export type declarations are not supported
4486---------------------------------------------------------------
4487
4488|CB_RULE|
4489~~~~~~~~~
4490
4491|LANG| does not have a special notation for exporting types.
4492Use ordinary export instead.
4493
4494|CB_BAD|
4495~~~~~~~~
4496
4497.. code:: typescript
4498
4499    class C {}
4500    export type { C }
4501
4502|CB_OK|
4503~~~~~~~
4504
4505.. code:: typescript
4506
4507    export class C {}
4508    
4509