1.. 2 Copyright (c) 2021-2024 Huawei Device Co., Ltd. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 http://www.apache.org/licenses/LICENSE-2.0 7 Unless required by applicable law or agreed to in writing, software 8 distributed under the License is distributed on an "AS IS" BASIS, 9 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 See the License for the specific language governing permissions and 11 limitations under the License. 12 13.. _Experimental Features: 14 15Experimental Features 16##################### 17 18.. meta: 19 frontend_status: Partly 20 21This Chapter introduces the |LANG| features that are considered parts of 22the language, but have no counterpart in |TS|, and are therefore not 23recommended to those in need of a single source code for |TS| and |LANG|. 24 25Some features introduced in this Chapter are still under discussion. They can 26be removed from the final version of the |LANG| specification. Once a feature 27introduced in this Chapter is approved and/or implemented, the corresponding 28section is moved to the body of the specification as appropriate. 29 30The *array creation* feature introduced in :ref:`Array Creation Expressions` 31enables users to dynamically create objects of array type by using runtime 32expressions that provide the array size. This is a useful addition to other 33array-related features of the language, such as array literals. 34 35The construct can also be used to create multidimensional arrays. 36 37The feature *function and method overloading* is supported in many 38(if not all) modern programming languages. Overloading functions/methods 39is a practical and convenient way to write program actions that are similar 40in logic but different in implementation. 41 42.. index:: 43 implementation 44 array creation 45 runtime expression 46 array 47 array literal 48 construct 49 function overloading 50 method overloading 51 52The |LANG| language supports (as an experimental feature at the moment) two 53semantically and syntactically different implementations of overloading: the 54|TS|-like implementation, and that of other languages. See 55:ref:`Function and Method Overloading` for more details. 56 57Section :ref:`Native Functions and Methods` introduces practically important 58and useful mechanisms for the inclusion of components written in other languages 59into a program written in |LANG|. 60 61Section :ref:`Final Classes and Methods` discusses the well-known feature that 62in many OOP languages provides a way to restrict class inheritance and method 63overriding. Making a class *final* prohibits defining classes derived from it, 64whereas making a method *final* prevents it from overriding in derived classes. 65 66Section :ref:`Adding Functionality to Existing Types` defines the ability 67to add new functionality to already defined type. This 68feature can be used for GUI programming (:ref:`Support for GUI Programming`). 69 70Section :ref:`Enumeration Methods` adds methods to declarations of the 71enumeration types. Such methods can help in some kinds of manipulations 72with ``enums``. 73 74.. index:: 75 implementation 76 function overloading 77 method overloading 78 final class 79 method final 80 OOP (object-oriented programming) 81 inheritance 82 enum 83 class 84 interface 85 inheritance 86 derived class 87 88Section :ref:`Exceptions` discusses the powerful, commonly used mechanism for 89the processing of various kinds of unexpected events and situations that break 90the *ordinary* program logic. There are constructs to raise (*throw*) 91exceptions, *catch* them along the dynamic sequence of function calls, and 92handle them. Some support for exceptions is also provided by the classes from 93the standard library (see :ref:`Standard Library`). 94 95**Note**: The exceptions mechanism is sometimes deprecated for being too 96time-consuming and unsafe. Some modern languages do not support the 97exceptions mechanism as discussed in this section. That is why the expediency 98of adding this feature to the language is still under discussion. 99 100The |LANG| language supports writing concurrent applications in the form of 101*coroutines* (see :ref:`Coroutines`) that allow executing functions 102concurrently, while the *channels* through which the coroutines can produce 103results are asynchronous. 104 105There is a basic set of language constructs that support concurrency. A function 106to be launched asynchronously is marked by adding the modifier ``async`` 107to its declaration. In addition, any function---or lambda expression---can be 108launched as a separate thread explicitly by using the launch expression. 109 110.. index:: 111 exception 112 construct 113 coroutine 114 channel 115 function 116 async modifier 117 launch expression 118 launch 119 lambda expression 120 concurrency 121 async modifier 122 123The ``await`` statement is introduced to synchronize functions launched as 124threads. The generic class ``Promise<T>`` from the standard library (see 125:ref:`Standard Library`) is used to exchange information between threads. 126The class can be handled as an implementation of the channel mechanism. 127The class provides a number of methods to manipulate the values produced 128by threads. 129 130Section :ref:`Packages` discusses a well-known and proven language feature 131intended to organize large pieces of software that typically consist of many 132components. *Packages* allow developers to construct a software product 133as a composition of subsystems, and organize the development process in a way 134that is appropriate for independent teams to work in parallel. 135 136.. index:: 137 await statement 138 function 139 launch 140 generic class 141 standard library 142 implementation 143 channel 144 package 145 construct 146 147*Package* is the language construct that combines a number of declarations, 148and makes them parts of an independent compilation unit. 149 150The *export* and *import* features are used to organize communication between 151*packages*. An entity exported from one package becomes known to---and 152accessible (see :ref:`Accessible`) in---another package which imports that 153feature. Various options are provided to simplify export/import, e.g., by 154defining non-exported, i.e., ``internal`` declarations that are not accessible 155(see :ref:`Accessible`) from the outside of the package. 156 157In addition, |LANG| supports the *package* initialization semantics that 158makes a *package* even more independent from the environment. 159 160 161.. index:: 162 package 163 construct 164 declaration 165 compilation unit 166 export 167 import 168 internal declaration 169 non-exported declaration 170 access 171 initialization 172 semantics 173 174| 175 176.. _Character Type and Literals: 177 178Character Type and Literals 179*************************** 180 181| 182 183.. _Character Literals: 184 185Character Literals 186================== 187 188.. meta: 189 frontend_status: Done 190 191A ``char literal`` represents the following: 192 193- A value with a single character; or 194- A single escape sequence preceded by the characters *single quote* (U+0027) 195 and '*c*' (U+0063), and followed by a *single quote* U+0027). 196 197 198.. code-block:: abnf 199 200 CharLiteral: 201 'c\'' SingleQuoteCharacter '\'' 202 ; 203 204 SingleQuoteCharacter: 205 ~['\\\r\n] 206 | '\\' EscapeSequence 207 ; 208 209The examples are presented below: 210 211.. code-block:: typescript 212 :linenos: 213 214 c'a' 215 c'\n' 216 c'\x7F' 217 c'\u0000' 218 219``Character Literals`` are of type ``char``. 220 221.. index:: 222 char literal 223 character literal 224 escape sequence 225 single quote 226 type char 227 228| 229 230.. _Character Type and Operations: 231 232Character Type and Operations 233============================= 234 235.. meta: 236 frontend_status: Partly 237 todo: need to adapt the implementation to the latest specification 238 239+-----------+----------------------------------+------------------------------+ 240| **Type** | **Type's Set of Values** | **Corresponding Class Type** | 241+===========+==================================+==============================+ 242| ``char`` | Symbols with codes from \U+0000 | *Char* | 243| | to \U+FFFF inclusive, that is, | | 244| | from *0* to *65,535* | | 245+-----------+----------------------------------+------------------------------+ 246 247|LANG| provides a number of operators to act on character values as discussed 248below. 249 250All character operators are identical to integer operators (see 251:ref:`Integer Types and Operations`) for they handle character values as 252integers of type ``int`` (see :ref:`Widening Primitive Conversions`). 253 254The class ``Char`` provides constructors, methods, and constants that are 255parts of the |LANG| standard library (see :ref:`Standard Library`). 256 257.. index:: 258 char 259 Char 260 boolean 261 equality operator 262 constructor 263 method 264 constant 265 266| 267 268.. _Array Creation Expressions: 269 270Array Creation Expressions 271************************** 272 273.. meta: 274 frontend_status: Done 275 276An *array creation expression* creates new objects that are instances of arrays. 277The *array literal* expression is used to create an array instance, and to 278provide some initial values (see :ref:`Array Literal`). 279 280.. code-block:: abnf 281 282 newArrayInstance: 283 'new' arrayElementType dimensionExpression+ (arrayElement)? 284 ; 285 286 arrayElementType: 287 typeReference 288 | '(' type ')' 289 ; 290 291 dimensionExpression: 292 '[' expression ']' 293 ; 294 295 arrayElement: 296 '(' expression ')' 297 ; 298 299.. code-block:: typescript 300 :linenos: 301 302 let x = new number[2][2] // create 2x2 matrix 303 304An *array creation expression* creates an object that is a new array with the 305elements of the type specified by ``arrayElelementType``. 306 307The type of each *dimensionExpression* must be convertible (see 308:ref:`Primitive Types Conversions`) to an integer type. Otherwise, 309a :index:`compile-time error` occurs. 310 311A numeric conversion (see :ref:`Primitive Types Conversions`) is performed 312on each *dimensionExpression* to ensure that the resultant type is ``int``. 313Otherwise, a :index:`compile-time error` occurs. 314 315A :index:`compile-time error` occurs if any *dimensionExpression* is a 316constant expression that is evaluated at compile time to a negative integer 317value. 318 319.. index:: 320 array creation expression 321 conversion 322 integer 323 type 324 value 325 numeric conversion 326 type int 327 constant expression 328 329If the type of any *dimensionExpression* is ``number`` or other floating-point 330type, and its fractional part is different from '0', then errors occur as 331follows: 332 333- A runtime error, if the situation is identified during program execution; and 334- A :index:`compile-time error`, if the situation is detected during 335 compilation. 336 337If ``arrayElement`` is provided, then the type of the ``expression`` can be 338as follows: 339 340- Type of array element denoted by ``arrayElelementType``, or 341- Lambda function with the return type equal to the type of array element 342 denoted by ``arrayElelementType`` and the parameters of type ``int``, and the 343 number of parameters equal to the number of array dimensions. 344 345.. index:: 346 type 347 floating-point type 348 runtime error 349 compilation 350 expression 351 lambda function 352 array 353 parameter 354 array 355 356Otherwise, a :index:`compile-time error` occurs. 357 358.. code-block:: typescript 359 :linenos: 360 361 let x = new number[-3] // compile-time error 362 363 let y = new number[3.141592653589] // compile-time error 364 365 foo (3.141592653589) 366 function foo (size: number) { 367 let y = new number[size] // runtime error 368 } 369 370 371A :index:`compile-time error` occurs if ``arrayElelementType`` refers to a 372class that does not contain an accessible (see :ref:`Accessible`) parameterless 373constructor, or constructor with all parameters of the second form of optional 374parameters (see :ref:`Optional Parameters`), or if ``type`` has no default 375value: 376 377.. code-block-meta: 378 expect-cte: 379 380.. code-block:: typescript 381 :linenos: 382 383 let x = new string[3] // compile-time error: string has no default value 384 385 class A { 386 constructor (p1?: number, p2?: string) {} 387 } 388 let y = new A[2] // OK, as all 3 elements of array will be filled with 389 // new A() objects 390 391A :index:`compile-time error` occurs if ``arrayElelementType`` is a type 392parameter: 393 394.. code-block:: typescript 395 :linenos: 396 397 class A<T> { 398 foo() { 399 new T[2] // compile-time error: cannot create an array of type parameter elements 400 } 401 } 402 403.. index:: 404 accessibility 405 constructor 406 array 407 408Creating an array with a known number of elements is presented below: 409 410.. code-block:: typescript 411 :linenos: 412 413 class A {} 414 // It has no default value or parameterless constructor defined 415 416 let array_size = 5 417 418 let array1 = new A[array_size] (new A) 419 /* Create array of 'array_size' elements and all of them will have 420 initial value equal to an object created by new A expression */ 421 422 let array2 = new A[array_size] ((index): A => { return new A }) 423 /* Create array of `array_size` elements and all of them will have 424 initial value equal to the result of lambda function execution with 425 different indices */ 426 427 let array2 = new A[2][3] ((index1, index2): A => { return new A }) 428 /* Create two-dimensional array of 6 elements total and all of them will 429 have initial value equal to the result of lambda function execution with 430 different indices */ 431 432Creating exotic arrays with different kinds of element types is presented below: 433 434.. code-block:: typescript 435 :linenos: 436 437 let array_of_union = new (Object|null) [5] // filled with null 438 let array_of_functor = new (() => void) [5] ( (): void => {}) 439 type aliasTypeName = number [] 440 let array_of_array = new aliasTypeName [5] ( [3.141592653589] ) 441 442| 443 444.. _Runtime Evaluation of Array Creation Expressions: 445 446Runtime Evaluation of Array Creation Expressions 447================================================ 448 449.. meta: 450 frontend_status: Partly 451 todo: initialize array elements properly - #14963, #15610 452 453The evaluation of an array creation expression at runtime is performed 454as follows: 455 456#. The dimension expressions are evaluated. The evaluation is performed 457 left-to-right; if any expression evaluation completes abruptly, then 458 the expressions to the right of it are not evaluated. 459 460#. The values of dimension expressions are checked. If the value of any 461 ``dimExpr`` expression is less than zero, then ``NegativeArraySizeError`` is 462 thrown. 463 464#. Space for the new array is allocated. If the available space is not 465 sufficient to allocate the array, then ``OutOfMemoryError`` is thrown, 466 and the evaluation of the array creation expression completes abruptly. 467 468#. When a one-dimensional array is created, each element of that array 469 is initialized to its default value if type default value is defined 470 (:ref:`Default Values for Types`). 471 If the default value for an element type is not defined, but the element 472 type is a class type, then its *parameterless* constructor is used to 473 create the value of each element. 474 475#. When a multidimensional array is created, the array creation effectively 476 executes a set of nested loops of depth *n-1*, and creates an implied 477 array of arrays. 478 479.. index:: 480 array 481 constructor 482 abrupt completion 483 expression 484 runtime 485 evaluation 486 default value 487 parameterless constructor 488 class type 489 initialization 490 nested loop 491 492| 493 494.. _Indexable Types: 495 496Indexable Types 497*************** 498 499.. meta: 500 frontend_status: Done 501 502If a class or an interface declares one or two functions with names ``$_get`` 503and ``$_set``, and signatures *(index: Type1): Type2* and *(index: Type1, 504value: Type2)* respectively, then an indexing expression (see 505:ref:`Indexing Expressions`) can be applied to variables of such types: 506 507.. code-block-meta: 508 509.. code-block:: typescript 510 :linenos: 511 512 class SomeClass { 513 $_get (index: number): SomeClass { return this } 514 $_set (index: number, value: SomeClass) { } 515 } 516 let x = new SomeClass 517 x = x[1] // This notation implies a call: x = x.$_get (1) 518 x[1] = x // This notation implies a call: x.$_set (1, x) 519 520If only one function is present, then only the appropriate form of the index 521expressions (see :ref:`Indexing Expressions`) is available: 522 523.. code-block-meta: 524 expect-cte: 525 526.. code-block:: typescript 527 :linenos: 528 529 class ClassWithGet { 530 $_get (index: number): ClassWithGet { return this } 531 } 532 let getClass = new ClassWithGet 533 getClass = getClass[0] 534 getClass[0] = getClass // Error - no $_set function available 535 536 class ClassWithSet { 537 $_set (index: number, value: ClassWithSet) { } 538 } 539 let setClass = new ClassWithSet 540 setClass = setClass[0] // Error - no $_get function available 541 setClass[0] = setClass 542 543 544.. index:: 545 function 546 signature 547 indexing expression 548 variable 549 index expression 550 string 551 552Type ``string`` can be used as a type of the index parameter: 553 554.. code-block-meta: 555 556.. code-block:: typescript 557 :linenos: 558 559 class SomeClass { 560 $_get (index: string): SomeClass { return this } 561 $_set (index: string, value: SomeClass) { } 562 } 563 let x = new SomeClass 564 x = x["index string"] 565 // This notation implies a call: x = x.$_get ("index string") 566 x["index string"] = x 567 // This notation implies a call: x.$_set ("index string", x) 568 569Functions ``$_get`` and ``$_set`` are ordinary functions with compiler-known 570signatures. The functions can be used like any other function. 571The functions can be abstract, or defined in an interface and implemented later. 572The functions can be overridden and provide a dynamic dispatch for the indexing 573expression evaluation (see :ref:`Indexing Expressions`). The functions can be 574used in generic classes and interfaces for better flexibility. A 575:index:`compile-time error` occurs if these functions are marked as ``async``. 576 577.. index:: 578 index parameter 579 function 580 compiler 581 signature 582 overriding 583 interface 584 implementation 585 indexing expression 586 evaluation 587 flexibility 588 async function 589 generic class 590 591.. code-block-meta: 592 expect-cte: 593 594.. code-block:: typescript 595 :linenos: 596 597 interface ReadonlyIndexable<K, V> { 598 $_get (index: K): V 599 } 600 601 interface Indexable<K, V> extends ReadonlyIndexable<K, V> { 602 $_set (index: K, value: V) 603 } 604 605 class IndexableByNumber<V> extends Indexable<number, V> { 606 private data: V[] = [] 607 $_get (index: number): V { return this.data [index] } 608 $_set (index: number, value: V) { this.data[index] = value } 609 } 610 611 class IndexableByString<V> extends Indexable<string, V> { 612 private data = new Map<string, V> 613 $_get (index: string): V { return this.data [index] } 614 $_set (index: string, value: V) { this.data[index] = value } 615 } 616 617 class BadClass extends IndexableByNumber<boolean> { 618 override $_set (index: number, value: boolean) { index / 0 } 619 } 620 621 let x: IndexableByNumber<boolean> = new BadClass 622 x[666] = true // This will be dispatched at runtime to the overridden 623 // version of the $_set method 624 x.$_get (15) // $_get and $_set can be called as ordinary 625 // methods 626 627| 628 629.. _Iterable Types: 630 631Iterable Types 632************** 633 634.. meta: 635 frontend_status: Done 636 637A class or an interface can be made *iterable*, meaning that their instances 638can be used in ``for-of`` statements (see :ref:`For-Of Statements`). 639 640Some type ``C`` is *iterable* if it declares a parameterless function with name 641``$_iterator`` with the return type which is compatible (see 642:ref:`Type Compatibility`) with type ``Iterator``, defined in the standard 643library (see :ref:`Standard Library`). It guarantees the object returned 644is of the class type which implements ``Iterator``, and thus allows traversing 645an object of class type ``C``. The example below defines *iterable* class ``C``: 646 647.. index:: 648 iterable type 649 class 650 interface 651 instance 652 for-of statement 653 parameterless function 654 compatibility 655 iterable class 656 657.. code-block:: typescript 658 :linenos: 659 660 class C { 661 data: string[] = ['a', 'b', 'c'] 662 $_iterator() { // Function type is inferred from its body 663 return new CIterator(this) 664 } 665 } 666 667 class CIterator implements Iterator<string> { 668 index = 0 669 base: C 670 constructor (base: C) { 671 this.base = base 672 } 673 next(): IteratorResult<string> { 674 return { 675 done: this.index >= this.base.data.length, 676 value: this.index >= this.base.data.length ? undefined : this.base.data[this.index++] 677 } 678 } 679 } 680 681 let c = new C() 682 for (let x of c) { 683 console.log(x) 684 } 685 686In the example above, class ``C`` function ``$_iterator`` returns 687``CIterator<string>`` that implements ``Iterator<string>``. If executed, 688this code prints out the following: 689 690.. code-block:: typescript 691 692 "a" 693 "b" 694 "c" 695 696 697The function ``$_iterator`` is an ordinary function with a compiler-known 698signature. The function can be used like any other function. It can be 699abstract or defined in an interface to be implemented later. A 700:index:`compile-time error` occurs if this function is marked as ``async``. 701 702.. index:: 703 function 704 class 705 string 706 iterator 707 compiler 708 signature 709 async function 710 711**Note**: To support the code compatible with |TS|, the name of the function 712``$_iterator`` can be written as ``[Symbol.iterator]``. In this case, the class 713``iterable`` looks as follows: 714 715.. code-block-meta: 716 717.. code-block:: typescript 718 :linenos: 719 720 class C { 721 data: string[] = ['a', 'b', 'c']; 722 [Symbol.iterator]() { 723 return new CIterator(this) 724 } 725 } 726 727The use of the name ``[Symbol.iterator]`` is considered deprecated. 728It can be removed in the future versions of the language. 729 730.. index:: 731 compatibility 732 function 733 iterator 734 class 735 736| 737 738.. _Callable Types: 739 740Callable Types 741************** 742 743.. meta: 744 frontend_status: Done 745 746A type is *callable* if the name of the type can be used in a call expression. 747A call expression that uses the name of a type is called a *type call 748expression*. Only class type can be callable. To make a type 749callable, a static method with the name ``invoke`` or ``instantiate`` must be 750defined or inherited: 751 752.. code-block-meta: 753 754.. code-block:: typescript 755 :linenos: 756 757 class C { 758 static invoke() { console.log("invoked") } 759 } 760 C() // prints: invoked 761 C.invoke() // also prints: invoked 762 763In the above example, ``C()`` is a *type call expression*. It is the short 764form of the normal method call ``C.invoke()``. Using an explicit call is always 765valid for the methods ``invoke`` and ``instantiate``. 766 767.. index:: 768 callable type 769 call expression 770 expression 771 type call expression 772 class type 773 method call 774 instantiation 775 776**Note**: Only a constructor---not the methods ``invoke`` or ``instantiate``---is 777called in a *new expression*: 778 779.. code-block-meta: 780 781.. code-block:: typescript 782 :linenos: 783 784 class C { 785 static invoke() { console.log("invoked") } 786 constructor() { console.log("constructed") } 787 } 788 let x = new C() // constructor is called 789 790The methods ``invoke`` and ``instantiate`` are similar but have differences as 791discussed below. 792 793A :index:`compile-time error` occurs if a callable type contains both methods 794``invoke`` and ``instantiate``. 795 796.. index:: 797 method 798 instantiation 799 800| 801 802.. _Callable Types with Invoke Method: 803 804Callable Types with Invoke Method 805================================= 806 807.. meta: 808 frontend_status: Done 809 810The method ``invoke`` can have an arbitrary signature. The method can be used 811in a *type call expression* in either case above. If the signature has 812parameters, then the call must contain corresponding arguments. 813 814.. code-block-meta: 815 816.. code-block:: typescript 817 :linenos: 818 819 class Add { 820 static invoke(a: number, b: number): number { 821 return a + b 822 } 823 } 824 console.log(Add(2, 2)) // prints: 4 825 826.. index:: 827 callable type 828 signature 829 method 830 type call expression 831 argument 832 833| 834 835.. _Callable Types with Instantiate Method: 836 837Callable Types with Instantiate Method 838====================================== 839 840.. meta: 841 frontend_status: Partly 842 todo: es2panda segfaults on the first example 843 844The method ``instantiate`` can have an arbitrary signature by itself. 845If it is to be used in a *type call expression*, then its first parameter 846must be a ``factory`` (i.e., it must be a *parameterless function type 847returning some class or struct type*). 848The method can have or not have other parameters, and those parameters can 849be arbitrary. 850 851In a *type call expression*, the argument corresponding to the ``factory`` 852parameter is passed implicitly: 853 854.. code-block:: typescript 855 :linenos: 856 857 class C { 858 static instantiate(factory: () => C): C { 859 return factory() 860 } 861 } 862 let x = C() // factory is passed implicitly 863 864 // Explicit call of 'instantiate' requires explicit 'factory': 865 let y = C.instantiate(() => { return new C()}) 866 867.. index:: 868 method 869 signature 870 type call expression 871 factory 872 parameterless function type 873 struct type 874 875If the method ``instantiate`` has additional parameters, then the call must 876contain corresponding arguments: 877 878.. code-block:: typescript 879 :linenos: 880 881 class C { 882 name = "" 883 static instantiate(factory: () => C, name: string): C { 884 let x = factory() 885 x.name = name 886 return x 887 } 888 } 889 let x = C("Bob") // factory is passed implicitly 890 891A :index:`compile-time error` occurs in a *type call expression* with type ``T``, 892if: 893 894- ``T`` has neither method ``invoke`` nor method ``instantiate``; or 895- ``T`` has the method ``instantiate`` but its first parameter is not 896 a ``factory``. 897 898.. index:: 899 type call expression 900 instantiation 901 method 902 parameter 903 904.. code-block-meta: 905 expect-cte 906 907.. code-block:: typescript 908 :linenos: 909 910 class C { 911 static instantiate(factory: string): C { 912 return factory() 913 } 914 } 915 let x = C() // compile-time error, wrong 'instantiate' 1st parameter 916 917| 918 919.. _Statements Experimental: 920 921Statements 922********** 923 924.. meta: 925 frontend_status: Done 926 927| 928 929 930.. _For-of Type Annotation: 931 932For-of Type Annotation 933====================== 934 935.. meta: 936 frontend_status: Done 937 938An explicit type annotation is allowed for a *for-variable*: 939 940.. code-block:: typescript 941 :linenos: 942 943 // explicit type is used for a new variable, 944 let x: number[] = [1, 2, 3] 945 for (let n: number of x) { 946 console.log(n) 947 } 948 949.. index:: 950 type annotation 951 for-variable 952 for-of type annotation 953 954| 955 956.. _Multiple Catch Clauses in Try Statements: 957 958Multiple Catch Clauses in Try Statements 959======================================== 960 961.. meta: 962 frontend_status: Done 963 964When an exception or an error is thrown in the ``try`` block 965(see :ref:`try Statements`), or in a 966*throwing* or *rethrowing* function (see :ref:`Throwing Functions` and 967:ref:`Rethrowing Functions`) called from the ``try`` block, the control is 968transferred to the first ``catch`` clause if the statement has at least one 969``catch`` clause that can catch that exception or error. If no ``catch`` 970clause is found, then exception or error is propagated to the surrounding 971scope. 972 973**Note**: An exception handled within a *non-throwing* function (see 974:ref:`Non-Throwing Functions`) is never propagated outside that function. 975 976A ``catch`` clause has two parts: 977 978- Exception parameter that provides access to the object associated 979 with the exception or the error occurred; and 980 981- Block of code that is to handle the situation. 982 983.. index:: 984 exception 985 error 986 throwing function 987 rethrowing function 988 non-throwing function 989 try block 990 try statement 991 propagation 992 scope 993 catch clause 994 propagation 995 exception parameter 996 access 997 998*Default catch clause* is a ``catch`` clause with the exception parameter type 999omitted. Such a ``catch`` clause handles any exception or error that is not 1000handled by any previous clause. The type of that parameter is union 1001``Exception`` | ``Error``. 1002 1003A :index:`compile-time error` occurs if: 1004 1005- Default ``catch`` clause is not the last ``catch`` clause in a 1006 ``try`` statement. 1007 1008- Type reference of an exception parameter (if any) is neither the 1009 class ``Exception`` or ``Error``, nor a class derived from ``Exception`` or 1010 ``Error``. 1011 1012.. index:: 1013 catch clause 1014 default catch clause 1015 exception 1016 parameter type 1017 union 1018 try statement 1019 type reference 1020 error 1021 1022.. code-block-meta: 1023 1024.. code-block:: typescript 1025 :linenos: 1026 1027 class ZeroDivisorException extends Exception {} 1028 1029 function divide(a: int, b: int): int throws { 1030 if (b == 0) throw new ZeroDivisorException() 1031 return a / b 1032 } 1033 1034 function process(a: int; b: int) { 1035 try { 1036 let res = divide(a, b) 1037 1038 // Division successful, further processing ... 1039 } 1040 catch (d: ZeroDivisorException) { 1041 // Handle zero division situation 1042 } 1043 catch (e) { // type of 'e' is Error|Exception 1044 // Handle all other errors or exceptions 1045 } 1046 } 1047 1048 1049All exceptions that the ``try`` block can throw are caught by the function 1050*process*. Special handling is provided for the ``ZeroDivisor`` exception, 1051and the handling of other exceptions and errors is different. 1052 1053``Catch`` clauses do not handle every possible exception or error that can 1054be thrown by the code in the ``try`` block. If no ``catch`` clause can handle 1055the situation, then exception or error is propagated to the surrounding scope. 1056 1057**Note**: If a ``try`` statement (*default catch clause*) is placed inside a 1058*non-throwing* function (see :ref:`Non-Throwing Functions`), then exception 1059is never propagated. 1060 1061.. index:: 1062 exception 1063 try block 1064 exception 1065 propagation 1066 try statement 1067 default catch clause 1068 non-throwing function 1069 1070If a ``catch`` clause contains a block that corresponds to a parameter of the 1071error, then it can only handle that error. 1072 1073The type of the ``catch`` clause parameter in a *default catch clause* is 1074omitted. The ``catch`` clause can handle any exceptions or errors unhandled 1075by the previous clauses. 1076 1077The type of a ``catch`` clause parameter (if any) must be of the class 1078``Error`` or ``Exception``, or of another class derived from ``Exception`` 1079or ``Error``. 1080 1081.. index:: 1082 exception 1083 error 1084 catch clause 1085 default catch clause 1086 derived class 1087 Error 1088 Exception 1089 1090.. code-block:: typescript 1091 :linenos: 1092 1093 function process(a: int; b: int): int { 1094 try { 1095 return a / b 1096 } 1097 catch (x: DivideByZeroError) { return MaxInt } 1098 } 1099 1100A ``catch`` clause handles the ``DivideByZeroError`` at runtime. Other errors 1101are propagated to the surrounding scope if no ``catch`` clause is found. 1102 1103.. index:: 1104 catch clause 1105 runtime 1106 error 1107 propagation 1108 scope 1109 1110| 1111 1112.. _Function and Method Overloading: 1113 1114Function and Method Overloading 1115******************************* 1116 1117.. meta: 1118 frontend_status: Done 1119 1120Similarly to |TS|, the |LANG| language supports overload signatures that allow 1121specifying several headers for a function or method with different signatures. 1122Most other languages support a different form of overloading that specifies 1123a separate body for each overloaded header. 1124 1125Both approaches have their advantages and disadvantages. The latter approach 1126supported by |LANG| can deliver better performance because no extra checks 1127are performed during the execution of a specific body at runtime. 1128 1129.. index:: 1130 function overloading 1131 method overloading 1132 overload signature 1133 header 1134 function 1135 method 1136 signature 1137 overloaded header 1138 runtime 1139 1140| 1141 1142.. _Function Overloading: 1143 1144Function Overloading 1145==================== 1146 1147.. meta: 1148 frontend_status: Done 1149 1150If a declaration scope declares and/or imports two or more functions with the 1151same name but different signatures that are not *overload-equivalent* (see 1152:ref:`Overload-Equivalent Signatures`), then such functions are *overloaded*. 1153Function overloading declarations cause no :index:`compile-time error` on their 1154own. 1155 1156No specific relationship is required between the return types, or between the 1157``throws`` clauses of the two functions with the same name but different 1158signatures that are not *overload-equivalent* (see 1159:ref:`Overload-Equivalent Signatures`). 1160 1161When calling an overloaded function, the number of actual arguments (and any 1162explicit type arguments) and compile-time argument types are used at compile 1163time to determine exactly which one is to be called (see 1164:ref:`Function Call Expression`). 1165 1166.. index:: 1167 function overloading 1168 declaration scope 1169 signature 1170 name 1171 overload-equivalence 1172 overload-equivalent signature 1173 overloaded function name 1174 return type 1175 throws clause 1176 argument 1177 type argument 1178 function call 1179 compile-time error 1180 1181| 1182 1183.. _Class Method Overloading: 1184 1185Class Method Overloading 1186======================== 1187 1188.. meta: 1189 frontend_status: Done 1190 1191If two or more methods within a class have the same name, and their signatures 1192are not *overload-equivalent* (see :ref:`Overload-Equivalent Signatures`), then 1193such methods are considered *overloaded*. 1194 1195Method overloading declarations cause no :index:`compile-time error` on their 1196own, except where a possible instantiation causes an *overload-equivalent* (see 1197:ref:`Overload-Equivalent Signatures`) method in the instantiated class or 1198interface: 1199 1200.. index:: 1201 class method overloading 1202 class 1203 signature 1204 overload-equivalent signature 1205 overload equivalence 1206 overloading 1207 method 1208 instantiation 1209 interface 1210 1211.. code-block:: typescript 1212 :linenos: 1213 1214 class Template<T> { 1215 foo (p: number) { ... } 1216 foo (p: T) { ... } 1217 } 1218 let instantiation: Template<number> 1219 // Leads to two *overload-equivalent* methods 1220 1221 interface ITemplate<T> { 1222 foo (p: number) 1223 foo (p: T) 1224 } 1225 function foo (instantiation: ITemplate<number>) { ... } 1226 // Leads to two *overload-equivalent* methods 1227 1228 1229 1230If the signatures of two or more methods with the same name are not 1231*overload-equivalent* (see :ref:`Overload-Equivalent Signatures`), then the 1232return types of those methods, or the ``throws`` or ``rethrows`` clauses of 1233those methods can have any kind of relationship. 1234 1235When calling an overloaded method, the number of actual arguments (and any 1236explicit type arguments) and compile-time argument types are used at compile 1237time to determine exactly which one is to be called (see 1238:ref:`Method Call Expression`, and :ref:`Step 2 Selection of Method`). 1239 1240.. index:: 1241 signature 1242 overload-equivalent signature 1243 overload equivalence 1244 throws clause 1245 rethrows clause 1246 type argument 1247 argument type 1248 method call 1249 instance method 1250 1251| 1252 1253.. _Constructor Overloading: 1254 1255Constructor Overloading 1256======================= 1257 1258.. meta: 1259 frontend_status: Done 1260 1261Constructor overloading behavior is identical to that of method overloading (see 1262:ref:`Class Method Overloading`). Each class instance creation expression (see 1263:ref:`New Expressions`) resolves the constructor overloading call if any at 1264compile time. 1265 1266.. index:: 1267 constructor overloading 1268 method overloading 1269 class instance 1270 creation expression 1271 compile time 1272 1273| 1274 1275.. _Declaration Distinguishable by Signatures: 1276 1277Declaration Distinguishable by Signatures 1278========================================= 1279 1280.. meta: 1281 frontend_status: Done 1282 1283Same-name declarations are distinguishable by signatures if such 1284declarations are one of the following: 1285 1286- Functions with the same name and signatures that are not 1287 *overload-equivalent* (see :ref:`Overload-Equivalent Signatures` and 1288 :ref:`Function Overloading`). 1289 1290- Methods with the same name and signatures that are not 1291 *overload-equivalent* (see :ref:`Overload-Equivalent Signatures`, 1292 :ref:`Class Method Overloading`, and :ref:`Interface Method Overloading`). 1293 1294- Constructors of the same class and signatures that are not 1295 *overload-equivalent* (see :ref:`Overload-Equivalent Signatures` and 1296 :ref:`Constructor Overloading`). 1297 1298.. index:: 1299 distinguishable declaration 1300 signature 1301 function 1302 overloading 1303 overload-equivalent signature 1304 overload-equivalence 1305 constructor 1306 1307The example below represents the functions distinguishable by signatures: 1308 1309.. code-block:: typescript 1310 :linenos: 1311 1312 function foo() {} 1313 function foo(x: number) {} 1314 function foo(x: number[]) {} 1315 function foo(x: string) {} 1316 1317The following example represents the functions undistinguishable by signatures 1318that cause a :index:`compile-time error`: 1319 1320.. code-block:: typescript 1321 :linenos: 1322 1323 // Functions have overload-equivalent signatures 1324 function foo(x: number) {} 1325 function foo(y: number) {} 1326 1327 // Functions have overload-equivalent signatures 1328 function foo(x: number) {} 1329 type MyNumber = number 1330 function foo(x: MyNumber) {} 1331 1332.. index:: 1333 distinguishable function 1334 function 1335 signature 1336 1337| 1338 1339| 1340 1341.. _Native Functions and Methods: 1342 1343Native Functions and Methods 1344**************************** 1345 1346.. meta: 1347 frontend_status: Done 1348 1349| 1350 1351.. _Native Functions: 1352 1353Native Functions 1354================ 1355 1356.. meta: 1357 frontend_status: Done 1358 1359A native function is a function that marked with ``native`` keyword (see :ref:`Function Declarations`). 1360 1361A ``native`` function implemented in a platform-dependent code is typically 1362written in another programming language (e.g., *C*). A :index:`compile-time error` 1363occurs if a ``native`` function has a body. 1364 1365.. index:: 1366 keyword native 1367 function 1368 native function 1369 implementation 1370 platform-dependent code 1371 compile-time error 1372 function body 1373 1374| 1375 1376.. _Native Methods Experimental: 1377 1378Native Methods 1379============== 1380 1381.. meta: 1382 frontend_status: Done 1383 1384A native method is a method that marked with ``native`` keyword (see :ref:`Method Declarations`). 1385 1386``Native`` methods are the methods implemented in a platform-dependent code 1387written in another programming language (e.g., *C*). 1388 1389A :index:`compile-time error` occurs if: 1390 1391- The method declaration contains the keyword ``abstract`` along with the 1392 keyword ``native``. 1393 1394- The ``native`` method has a body (see :ref:`Method Body`) that is a block 1395 instead of a simple semicolon or empty body. 1396 1397.. index:: 1398 native method 1399 implementation 1400 platform-dependent code 1401 keyword native 1402 method body 1403 block 1404 method declaration 1405 keyword abstract 1406 semicolon 1407 empty body 1408 1409| 1410 1411.. _Native Constructors: 1412 1413Native Constructors 1414=================== 1415 1416.. meta: 1417 frontend_status: None 1418 1419A native constructor is a constructor that marked with ``native`` keyword (see :ref:`Constructor Declaration`). 1420 1421``Native`` constructors are the constructors implemented in a platform-dependent code 1422written in another programming language (e.g., *C*). 1423 1424A :index:`compile-time error` occurs if: 1425 1426- The ``native`` constructor has a non-empty body (see :ref:`Constructor Body`). 1427 1428.. index:: 1429 native constructor 1430 platform-dependent code 1431 keyword native 1432 non-empty body 1433 1434| 1435 1436.. _Final Classes and Methods: 1437 1438Final Classes and Methods 1439************************* 1440 1441.. meta: 1442 frontend_status: Done 1443 1444| 1445 1446.. _Final Classes Experimental: 1447 1448Final Classes 1449============= 1450 1451.. meta: 1452 frontend_status: Done 1453 1454A class can be declared ``final`` to prevent extension, i.e., a class declared 1455``final`` cannot have subclasses. No method of a ``final`` class can be 1456overridden. 1457 1458If a class type ``F`` expression is declared *final*, then only a class ``F`` 1459object can be its value. 1460 1461A :index:`compile-time error` occurs if the ``extends`` clause of a class 1462declaration contains another class that is ``final``. 1463 1464.. index:: 1465 final class 1466 method 1467 overriding 1468 class 1469 class extension 1470 extends clause 1471 class declaration 1472 subclass 1473 1474| 1475 1476.. _Final Methods Experimental: 1477 1478Final Methods 1479============= 1480 1481.. meta: 1482 frontend_status: Done 1483 1484A method can be declared ``final`` to prevent it from being overridden (see 1485:ref:`Overloading and Overriding`) in subclasses. 1486 1487A :index:`compile-time error` occurs if: 1488 1489- The method declaration contains the keyword ``abstract`` or ``static`` 1490 along with the keyword ``final``. 1491 1492- A method declared ``final`` is overridden. 1493 1494.. index:: 1495 final method 1496 overriding 1497 instance method 1498 subclass 1499 method declaration 1500 keyword abstract 1501 keyword static 1502 keyword final 1503 1504| 1505 1506.. _Default Interface Method Declarations: 1507 1508Default Interface Method Declarations 1509************************************* 1510 1511.. meta: 1512 frontend_status: Done 1513 1514.. code-block:: abnf 1515 1516 interfaceDefaultMethodDeclaration: 1517 'private'? identifier signature block 1518 ; 1519 1520A default method can be explicitly declared ``private`` in an interface body. 1521 1522A block of code that represents the body of a default method in an interface 1523provides a default implementation for any class if such class does not override 1524the method that implements the interface. 1525 1526.. index:: 1527 default method 1528 method declaration 1529 private 1530 implementation 1531 default method body 1532 interface body 1533 default implementation 1534 overriding 1535 1536| 1537 1538.. _Adding Functionality to Existing Types: 1539 1540Adding Functionality to Existing Types 1541************************************** 1542 1543|LANG| supports adding functions and accessors to already defined types, 1544so its usage looks the same, as if they are methods and accessors of these types. 1545The mechanism used is called: :ref:`Functions with Receiver` and 1546:ref:`Accessors with Receiver`. This feature is often used to add new 1547functionality to a class without having to inherit from this class. 1548However, it can be used not only for classes but for other types as well. 1549 1550Additionally, :ref:`Function Types with Receiver` and 1551:ref:`Lambda Expressions with Receiver` can be defined and use, 1552making the code more flexible. 1553 1554.. _Functions with Receiver: 1555 1556Functions with Receiver 1557======================= 1558 1559.. meta: 1560 frontend_status: None 1561 todo: import/export of them, function with receiver of primitive types or array 1562 1563A *function with receiver* declaration is a top-level declaration 1564(see :ref:`Top-Level Declarations`) that looks almost the same as 1565:ref:`Function Declarations`, except that the first parameter is mandatory, 1566and keyword ``this`` is used as its name: 1567 1568.. code-block:: abnf 1569 1570 functionWithReceiverDeclaration: 1571 'function' identifier typeParameters? signatureWithReceiver block 1572 ; 1573 1574 signatureWithReceiver: 1575 '(' receiverParameter (', ' parameterList)? ')' returnType? throwMark? 1576 ; 1577 1578 receiverParameter: 1579 'this' ':' 'readonly'? type 1580 ; 1581 1582There are two ways to call a *function with receiver*: 1583 1584- as a function call (see :ref:`Function Call Expression`), 1585 passing the first parameter in the usual way 1586 1587- as a method call (see :ref:`Method Call Expression`), where 1588 no argument is provided for the first parameter 1589 and the ``objectReference`` before 1590 the function name is used as the first argument 1591 1592.. code-block:: typescript 1593 :linenos: 1594 1595 class C {} 1596 1597 function foo(this: C) {} 1598 function bar(this: C, n: number): void {} 1599 1600 let c = new C() 1601 1602 // as a function call: 1603 foo(c) 1604 bar(c, 1) 1605 1606 // as a method call: 1607 c.foo() 1608 c.bar(1) 1609 1610The keyword ``this`` can be used inside a *function with receiver* 1611and it corresponds the first parameter. 1612 1613The type of ``this`` parameter is called the *receiver type* 1614(see :ref:`Receiver Type`). 1615 1616 1617If the *receiver type* is a class type, ``private`` or ``protected`` 1618members are not accessible (see :ref:`Accessible`) within the bodies of thee 1619*function with receiver*. Only ``public`` members can be accessed: 1620 1621.. index:: 1622 keyword this 1623 private 1624 protected 1625 access 1626 1627.. code-block:: typescript 1628 :linenos: 1629 1630 class A { 1631 foo () { ... this.bar() ... } 1632 // function bar() is accessible here 1633 protected member_1 ... 1634 private member_2 ... 1635 } 1636 function bar(this: A) { ... 1637 this.foo() // Method foo() is accessible as it is public 1638 this.member_1 // Compile-time error as member_1 is not accessible 1639 this.member_2 // Compile-time error as member_2 is not accessible 1640 ... 1641 } 1642 let a = new A() 1643 a.foo() // Ordinary class method is called 1644 a.bar() // Function with receiver is called 1645 1646The name of a *function with receiver* cannot be the same as the name of some 1647public receiver method or field, otherwise a :index:`compile-time error` occurs. 1648It also means, that a *function with receiver* cannot overload a method, 1649defined for receiver type. 1650 1651*Function with receiver* can be generic as in the following example: 1652 1653.. code-block:: typescript 1654 :linenos: 1655 1656 function foo<T>(this: B<T>, p: T) { 1657 console.log (p) 1658 } 1659 function demo (p1: B<SomeClass>, p2: B<BaseClass>) { 1660 p1.foo(new SomeClass()) 1661 // Type inference should determine the instantiating type 1662 p2.foo<BaseClass>(new DerivedClass()) 1663 // Explicit instantiation 1664 } 1665 1666*Functions with receiver* are dispatched statically; 1667what function is being called is known at compile time based 1668on the receiver type specified in its declaration. 1669 1670They can be applied to receiver of any 1671derived class until it is redefined in the derived class: 1672 1673.. code-block:: typescript 1674 :linenos: 1675 1676 class Base { ... } 1677 class Derived extends Base { ... } 1678 1679 function foo(this: Base) { console.log ("Base.foo is called") } 1680 function foo(this: Derived) { console.log ("Derived.foo is called") } 1681 1682 let b: Base = new Base() 1683 b.foo() // `Base.foo is called` to be printed 1684 b = new Derived() 1685 b.foo() // `Base.foo is called` to be printed 1686 let d: Derived = new Derived() 1687 d.foo() // `Derived.foo is called` to be printed 1688 1689As illustrated by the following examples, a *function with receiver* can be 1690defined in a compilation unit other than one that defines a receiver type: 1691 1692.. code-block:: typescript 1693 :linenos: 1694 1695 // file a.sts 1696 class A { 1697 foo() { ... } 1698 } 1699 1700 // file ext.sts 1701 import {A} from "a.sts" // name 'A' is imported 1702 function bar(this: A) () { 1703 this.foo() // Method foo() is called 1704 } 1705 1706| 1707 1708.. _Receiver Type: 1709 1710Receiver Type 1711============= 1712 1713A *receiver type* is a type of *receiver parameter* in functions, function types 1714and lamdbas with receiver. 1715 1716A *receiver type* may be an interface type, a class type, an array type 1717or a type parameter, otherwise a :index:`compile-time error` occurs. 1718 1719Using an array type as receiever type is illustrated by the example below: 1720 1721.. code-block:: typescript 1722 :linenos: 1723 1724 function addElements(this: number[], ...s: number[]) { 1725 ... 1726 } 1727 1728 let x: number[] = [1, 2] 1729 x.addElements(3, 4) 1730 1731| 1732 1733.. _Accessors with Receiver: 1734 1735Accessors with Receiver 1736======================= 1737 1738.. meta: 1739 frontend_status: None 1740 1741An *accessor with receiver* declaration is a top-level declaration 1742(see :ref:`Top-Level Declarations`) that can be used as class or interface 1743accessors (see :ref:`Accessor Declarations`) 1744for specified receiver type: 1745 1746.. code-block:: abnf 1747 1748 accessorWithReceiverDeclaration: 1749 'get' identifier '(' receiverParameter ')' returnType block 1750 | 'set' identifier '(' receiverParameter ',' parameter ')' block 1751 ; 1752 1753A get-accessor (getter) must have a single *received parameter* and an explicit return type. 1754A set-accessor (setter) must have a *received parameter*, and a second parameter and no return type. 1755 1756The use of getters and setters looks the same as the use of fields: 1757 1758.. code-block:: typescript 1759 :linenos: 1760 1761 class Person { 1762 firstName: string 1763 lastName: string 1764 constructor (first: string, last: string) {...} 1765 ... 1766 } 1767 1768 get fullName(this: C): string { 1769 return this.LastName + ' ' + this.FirstName 1770 } 1771 1772 let c = new C("John", "Doe") 1773 1774 // as a method call: 1775 console.log(c.fullName) // output: 'Doe John' 1776 c.fullName = "new name" // compile-time error, as setter is not defined 1777 1778A :index:`compile-time error` occurs if an accessor is used in form of 1779a function or a method call. 1780 1781| 1782 1783.. _Function Types with Receiver: 1784 1785Function Types with Receiver 1786============================ 1787 1788.. meta: 1789 frontend_status: None 1790 1791A *function type with receiver* specifies signature of functions or lambdas with receiver. 1792It is almost the same as a *function type* (see :ref:`Function Types`), 1793except that the first parameter is mandatory, 1794and keyword ``this`` is used as its name: 1795 1796.. code-block:: abnf 1797 1798 functionTypeWithReceiver: 1799 '(' receiverParameter (',' ftParameterList)? ')' ftReturnType 'throws'? 1800 ; 1801 1802The type of the *receiver parameter* is called a *receiver type* 1803(see :ref:`Receiver Type`). 1804 1805.. code-block:: typescript 1806 :linenos: 1807 1808 class A {...} 1809 1810 type FA = (this: A) => boolean 1811 type FN = (this: number[], max: number) => number 1812 1813*Function type with receiver* can be generic as in the following example: 1814 1815.. code-block:: typescript 1816 :linenos: 1817 1818 class B<T> {...} 1819 1820 type FB<T> = (this: B<T>, x: T): void 1821 type FBS = (this: B<string>, x: string): void 1822 1823 1824The usual rule of function type compatibility (see :ref:`Function Types Conversions`) 1825are applied to *function type with receiver*, ignoring parameters names. 1826 1827.. code-block:: typescript 1828 :linenos: 1829 1830 class A {...} 1831 1832 type F1 = (this: A) => boolean 1833 type F2 = (a: A) => boolean 1834 1835 function foo(this: A) => boolean {} 1836 function goo(a: A) => boolean {} 1837 1838 let f1: F1 = foo // ok 1839 f1 = goo // ok 1840 1841 let f2: F2 = goo // ok 1842 f2 = foo // ok 1843 f1 = f2 // ok 1844 1845The only difference is that only entity of function type with receiver can be 1846used in :ref:`Method Call Expression`. Using definitions from previous example: 1847 1848.. code-block:: typescript 1849 :linenos: 1850 1851 let a = new A() 1852 a.f1() // ok, function type with receiver 1853 f1(a) // ok 1854 1855 a.f2() // compile-time error 1856 f2(a) // ok 1857 1858| 1859 1860.. _Lambda Expressions with Receiver: 1861 1862Lambda Expressions with Receiver 1863================================ 1864 1865.. meta: 1866 frontend_status: None 1867 1868*Lambda expression with receiver* defines an instance of 1869a *function type with receiver* (see :ref:`Function Types with Receiver`). 1870 1871It looks almost the same as ordinary lambda expression 1872(see :ref:`Lambda Expressions`), except that the first parameter is mandatory, 1873and keyword ``this`` is used as its name: 1874 1875.. code-block:: abnf 1876 1877 lambdaExpressionWithReceiver: 1878 typeParameters? '(' receiverParameter (',' lambdaParameterList)? ')' 1879 returnType? throwMark? '=>' lambdaBody 1880 ; 1881 1882The keyword ``this`` can be used inside a *lamdba expression with receiver* 1883and it corresponds the first parameter: 1884 1885.. code-block:: typescript 1886 :linenos: 1887 1888 class A { name = "Bob" } 1889 1890 let show = (this: a): void { 1891 console.log(this.name) 1892 } 1893 1894The use of lambada is illustrated by the example below: 1895 1896.. code-block:: typescript 1897 :linenos: 1898 1899 class A { 1900 name: string 1901 constructor (n: string) { 1902 this.name = n 1903 } 1904 } 1905 1906 function apply(aa: A[], f: (this: A) => void) { 1907 for (let a of aa) { 1908 a.f() 1909 } 1910 } 1911 1912 let aa: A[] = [new A("aa"), new A("bb")] 1913 foo(aa, (this: A) => { console.log(this.name)} ) // output: "aa" "bb" 1914 1915| 1916 1917.. _Trailing Lambdas: 1918 1919Trailing Lambdas 1920**************** 1921 1922.. meta: 1923 frontend_status: Done 1924 1925The *trailing lambda* mechanism allows using a special form of function 1926or method call when the last parameter of a function or a method is of 1927function type, and the argument is passed as a lambda using the ``{}`` 1928notation. 1929 1930Syntactically, the *trailing lambda* looks as follows: 1931 1932.. index:: 1933 trailing lambda 1934 function call 1935 method call 1936 parameter 1937 function type 1938 method 1939 parameter 1940 lambda 1941 function type 1942 1943.. code-block:: typescript 1944 :linenos: 1945 1946 class A { 1947 foo (f: ()=>void) { ... } 1948 } 1949 1950 let a = new A() 1951 a.foo() { console.log ("method lambda argument is activated") } 1952 // method foo receives last argument as an inline lambda 1953 1954The formal syntax of the *trailing lambda* is presented below: 1955 1956.. code-block:: abnf 1957 1958 trailingLambdaCall: 1959 ( objectReference '.' identifier typeArguments? 1960 | expression ('?.' | typeArguments)? 1961 ) 1962 arguments block 1963 ; 1964 1965 1966Currently, no parameter can be specified for the trailing lambda. Otherwise, 1967a :index:`compile-time error` occurs. 1968 1969**Note**: If a call is followed by a block, and the function or method 1970being called has no last function type parameter, then such block is 1971handled as an ordinary block of statements but not as a lambda function. 1972 1973In case of other ambiguities (e.g., when a function or method call has the 1974last parameter, which can be optional, of a function type), a syntax 1975production that starts with '{' following the function or method call is 1976handled as the *trailing lambda*. 1977If other semantics is needed, then the semicolon '``;``' separator can be used. 1978It means that the function or the method is to be called without the last 1979argument (see :ref:`Optional Parameters`). 1980 1981.. index:: 1982 trailing lambda 1983 parameter 1984 block 1985 function 1986 method 1987 function type 1988 lambda function 1989 lambda 1990 semicolon 1991 call 1992 1993.. code-block:: typescript 1994 :linenos: 1995 1996 class A { 1997 foo (p?: ()=>void) { ... } 1998 } 1999 2000 let a = new A() 2001 a.foo() { console.log ("method lambda argument is activated") } 2002 // method foo receives last argument as an inline lambda 2003 2004 a.foo(); { console.log ("that is the block code") } 2005 // method 'foo' is called with 'p' parameter set to 'undefined' 2006 // ';' allows to specify explicitly that '{' starts the block 2007 2008 function bar(f: ()=>void) { ... } 2009 2010 bar() { console.log ("function lambda argument is activated") } 2011 // function 'bar' receives last argument as an inline lambda, 2012 bar(); { console.log ("that is the block code") } 2013 // function 'bar' is called with 'p' parameter set to 'undefined' 2014 2015 2016.. code-block:: typescript 2017 :linenos: 2018 2019 function foo (f: ()=>void) { ... } 2020 function bar (n: number) { ... } 2021 2022 foo() { console.log ("function lambda argument is activated") } 2023 // function foo receives last argument as an inline lambda, 2024 2025 bar(5) { console.log ("after call of 'bar' this block is executed") } 2026 2027 foo(() => { console.log ("function lambda argument is activated") }) 2028 { console.log ("after call of 'foo' this block is executed") } 2029 /* here, function foo receives lambda as an argument and a block after 2030 the call is just a block, not a trailing lambda. */ 2031 2032| 2033 2034.. _Enumeration Types Conversions: 2035 2036Enumeration Types Conversions 2037***************************** 2038 2039.. meta: 2040 frontend_status: Partly 2041 2042Every *enum* type is compatible with type ``Object`` (see 2043:ref:`Type Compatibility`). Every variable of type ``enum`` can thus be 2044assigned into a variable of type ``Object``. The ``instanceof`` check can 2045be used to get an enumeration variable back by applying the ``as`` conversion: 2046 2047.. code-block-meta: 2048 2049.. code-block:: typescript 2050 :linenos: 2051 2052 enum Commands { Open = "fopen", Close = "fclose" } 2053 let c: Commands = Commands.Open 2054 let o: Object = c // Autoboxing of enum type to its reference version 2055 // Such reference version type has no name, but can be detected by instanceof 2056 if (o instanceof Commands) { 2057 c = o as Commands // And explicitly converted back by 'as' conversion 2058 } 2059 2060.. index:: 2061 enum type 2062 enumeration type 2063 conversion 2064 assignment 2065 Object 2066 variable 2067 compatibility 2068 2069| 2070 2071.. _Enumeration Methods: 2072 2073Enumeration Methods 2074******************* 2075 2076.. meta: 2077 frontend_status: Partly 2078 2079Several static methods are available to handle each enumeration type as follows: 2080 2081- Method ``values()`` returns an array of enumeration constants in the order of 2082 declaration. 2083- Method ``getValueOf(name: string)`` returns an enumeration constant with the 2084 given name, or throws an error if no constant with such name exists. 2085 2086.. index:: 2087 enumeration method 2088 static method 2089 enumeration type 2090 enumeration constant 2091 error 2092 constant 2093 2094.. code-block:: typescript 2095 :linenos: 2096 2097 enum Color { Red, Green, Blue } 2098 let colors = Color.values() 2099 //colors[0] is the same as Color.Red 2100 let red = Color.valueOf("Red") 2101 2102There are additional methods for instances of any enumeration type: 2103 2104- Method ``valueOf()`` returns an ``int`` or ``string`` value of an enumeration 2105 constant depending on the type of the enumeration constant. 2106 2107- Method ``getName()`` returns the name of an enumeration constant. 2108 2109.. code-block-meta: 2110 2111.. code-block:: typescript 2112 :linenos: 2113 2114 enum Color { Red, Green = 10, Blue } 2115 let c: Color = Color.Green 2116 console.log(c.valueOf()) // prints 10 2117 console.log(c.getName()) // prints Green 2118 2119**Note**: ``c.toString()`` returns the same value as ``c.valueOf().toString()``. 2120 2121.. index:: 2122 instance 2123 enumeration type 2124 value 2125 numeric type 2126 enumeration constant 2127 type int 2128 type string 2129 2130| 2131 2132.. _Exceptions: 2133 2134Exceptions 2135********** 2136 2137.. meta: 2138 frontend_status: Done 2139 2140``Exception`` is the base class of all exceptions. ``Exception`` is used to 2141define a new exception, or any class derived from the ``Exception`` as the 2142base of a class: 2143 2144.. code-block:: typescript 2145 :linenos: 2146 2147 class MyException extends Exception { ... } 2148 2149.. index:: 2150 exception 2151 base class 2152 Exception 2153 2154A :index:`compile-time error` occurs if a generic class is a direct or 2155indirect subclass of ``Exception``. 2156 2157An exception is thrown explicitly with the ``throw`` statement. 2158 2159When an exception is thrown, the surrounding piece of code is to handle it by 2160correcting the problem, trying an alternative approach, or informing the user. 2161 2162An exception can be processed in two ways: 2163 2164- Propagating the exception from a function to the code that calls that 2165 function (see :ref:`Throwing Functions`); 2166 2167- Using a ``try`` statement to handle the exception (see :ref:`Try Statements`). 2168 2169.. index:: 2170 exception 2171 base class 2172 Exception 2173 try statement 2174 throw statement 2175 propagation 2176 function 2177 throwing function 2178 function call 2179 2180| 2181 2182.. _Throwing Functions: 2183 2184Throwing Functions 2185================== 2186 2187.. meta: 2188 frontend_status: Done 2189 2190The keyword ``throws`` is used at the end of a signature to indicate that a 2191function (this notion here includes methods, constructors, or lambdas) can 2192throw an exception. A function ending with ``throws`` is called a 2193*throwing function*. The function type can also be marked as ``throws``: 2194 2195.. index:: 2196 keyword throws 2197 throwing function 2198 signature 2199 method 2200 constructor 2201 lambda 2202 function 2203 exception 2204 function type 2205 throws mark 2206 2207.. code-block:: typescript 2208 :linenos: 2209 2210 function canThrow(x: int): int throws { ... } 2211 2212A *throwing function* can propagate exceptions to the scope from which 2213it is called. The propagation of an *exception* occurs if: 2214 2215- The call of a *throwing function* is not enclosed in a ``try`` statement; or 2216- The enclosed ``try`` statement does not contain a clause that can catch the 2217 exception. 2218 2219 2220In the example below, the function call is not enclosed in a ``try`` 2221statement; any exception raised by ``canThrow`` function is propagated: 2222 2223.. index:: 2224 throwing function 2225 propagation 2226 exception 2227 scope 2228 function call 2229 try statement 2230 2231.. code-block:: typescript 2232 :linenos: 2233 2234 function propagate1(x: int): int throws { 2235 return y = canThrow(x) // exception is propagated 2236 } 2237 2238 2239In the example below, the ``try`` statement can catch only ``this`` exceptions. 2240Any exception raised by ``canThrow`` function---except for ``MyException`` 2241itself, and any exception derived from ``MyException``---is propagated: 2242 2243.. index:: 2244 try statement 2245 this 2246 exception 2247 propagation 2248 2249.. code-block:: typescript 2250 :linenos: 2251 2252 function propagate2(x: int): int throws { 2253 try { 2254 return y = canThrow(x) // 2255 } 2256 catch (e: MyException) /*process*/ } 2257 return 0 2258 } 2259 2260| 2261 2262.. _Non-Throwing Functions: 2263 2264Non-Throwing Functions 2265====================== 2266 2267.. meta: 2268 frontend_status: Done 2269 2270A *non-throwing function* is a function (this notion here includes methods, 2271constructors, or lambdas) not marked as ``throws``. Any exceptions inside a 2272*non-throwing function* must be handled inside the function. 2273 2274A :index:`compile-time error` occurs if not **all** of the following 2275requirements are met: 2276 2277- The call of a *throwing function* is enclosed in a ``try`` statement; 2278- The enclosing ``try`` statement has a default ``catch`` clause. 2279 2280.. index:: 2281 non-throwing function 2282 throwing function 2283 function 2284 method 2285 constructor 2286 lambda 2287 throws mark 2288 try statement 2289 catch clause 2290 2291.. code-block-meta: 2292 expect-cte: 2293 2294.. code-block:: typescript 2295 :linenos: 2296 2297 // non-throwing function 2298 function cannotThrow(x: int): int { 2299 return y = canThrow(x) // compile-time error 2300 } 2301 2302 function cannotThrow(x: int): int { 2303 try { 2304 return y = canThrow(x) // 2305 } 2306 catch (e: MyException) { /* process */ } 2307 // compile-time error – default catch clause is required 2308 } 2309 2310| 2311 2312.. _Rethrowing Functions: 2313 2314Rethrowing Functions 2315==================== 2316 2317.. meta: 2318 frontend_status: Done 2319 2320A *rethrowing function* is a function that accepts a *throwing function* as a 2321parameter, and is marked with the keyword ``rethrows``. 2322 2323The body of such function must not contain any ``throw`` statement that is 2324not handled by a ``try`` statement within that body. A function with unhandled 2325``throw`` statements must be marked with the keyword ``throws`` but not 2326``rethrows``. 2327 2328.. index:: 2329 rethrowing function 2330 throwing function 2331 non-throwing function 2332 function parameter 2333 keyword throws 2334 keyword rethrows 2335 try statement 2336 throw statement 2337 2338Both a *throwing* and a *non-throwing* function can be an argument of a 2339*rethrowing function* ``foo`` that is being called. 2340 2341If a *throwing function* is an argument, then the calling of ``foo`` can 2342throw an exception. 2343 2344This rule is exception-free, i.e., a *non-throwing* function used as a call 2345argument cannot throw an exception: 2346 2347.. code-block:: typescript 2348 :linenos: 2349 2350 function foo (action: () throws) rethrows { 2351 action() 2352 } 2353 2354 function canThrow() { 2355 /* body */ 2356 } 2357 2358 function cannotThrow() { 2359 /* body */ 2360 } 2361 2362 // calling rethrowing function: 2363 foo(canThrow) // exception can be thrown 2364 foo(cannotThrow) // exception-free 2365 2366A call is exception-free if: 2367 2368- Function ``foo`` has several parameters of a function type marked 2369 with ``throws``; and 2370- All actual arguments of the call to ``foo`` are non-throwing. 2371 2372However, the call can raise an exception, and is handled as any other 2373*throwing function* call if at least one of the actual function arguments 2374is *throwing*. It implies that a call to ``foo`` within the body of a 2375*non-throwing* function must be guaranteed with a ``try-catch`` statement: 2376 2377.. index:: 2378 function 2379 exception-free call 2380 function type parameter 2381 throws mark 2382 throwing function 2383 non-throwing function 2384 try-catch statement 2385 2386.. code-block:: typescript 2387 :linenos: 2388 2389 function mayThrowContext() throws { 2390 // calling rethrowing function: 2391 foo(canThrow) // exception can be thrown 2392 foo(cannotThrow) // exception-free 2393 } 2394 2395 function neverThrowsContext() { 2396 try { 2397 // calling rethrowing function: 2398 foo(canThrow) // exception can be thrown 2399 foo(cannotThrow) // exception-free 2400 } 2401 catch (e) { 2402 // To handle the situation 2403 } 2404 } 2405 2406| 2407 2408.. _Exceptions and Initialization Expression: 2409 2410Exceptions and Initialization Expression 2411======================================== 2412 2413.. meta: 2414 frontend_status: Done 2415 2416A *variable declaration* (see :ref:`Variable Declarations`) or a *constant 2417declaration* (see :ref:`Constant Declarations`) expression used to initialize 2418a variable or constant must not have calls to functions that can *throw* or 2419*rethrow* exceptions if the declaration is not within a statement that handles 2420all exceptions. 2421 2422See :ref:`Throwing Functions` and :ref:`Rethrowing Functions` for details. 2423 2424.. index:: 2425 variable declaration 2426 exception 2427 initialization expression 2428 constant declaration 2429 expression 2430 initialization 2431 variable 2432 constant 2433 function call 2434 throw exception 2435 rethrow exception 2436 statement 2437 throwing function 2438 rethrowing function 2439 2440| 2441 2442.. _Exceptions and Errors Inside Field Initializers: 2443 2444Exceptions and Errors Inside Field Initializers 2445=============================================== 2446 2447.. meta: 2448 frontend_status: Done 2449 2450Class field initializers cannot call *throwing* or *rethrowing* functions. 2451 2452See :ref:`Throwing Functions` and :ref:`Rethrowing Functions` for details. 2453 2454.. index:: 2455 exception 2456 error 2457 field initializer 2458 throwing function 2459 rethrowing function 2460 2461| 2462 2463.. _Coroutines: 2464 2465Coroutines 2466********** 2467 2468.. meta: 2469 frontend_status: Partly 2470 todo: rename valueOf(string) to getValueOf(string), implement valueOf() 2471 2472A function or lambda can be a *coroutine*. |LANG| supports *basic coroutines*, 2473*structured coroutines*, and *communication channels*. 2474Basic coroutines are used to create and launch a coroutine; the result is then 2475to be awaited. 2476 2477.. index:: 2478 structured coroutine 2479 basic coroutine 2480 function 2481 lambda 2482 coroutine 2483 communication channel 2484 launch 2485 2486| 2487 2488.. _Create and Launch a Coroutine: 2489 2490Create and Launch a Coroutine 2491============================= 2492 2493.. meta: 2494 frontend_status: Done 2495 2496The following expression is used to create and launch a coroutine based on 2497a function call, a lambda call (see :ref:`Function Call Expression`), or a 2498method call (see :ref:`Method Call Expression`): 2499 2500.. code-block:: abnf 2501 2502 launchExpression: 2503 'launch' functionCallExpression | methodCallExpression; 2504 2505 2506.. code-block:: typescript 2507 :linenos: 2508 2509 let res = launch cof(10) 2510 2511 // where 'cof' can be defined as: 2512 function cof(a: int): int { 2513 let res: int 2514 // Do something 2515 return res 2516 } 2517 2518Lambda can be used in a launch expression as a part of a function call: 2519 2520.. code-block:: typescript 2521 :linenos: 2522 2523 let res = launch ((n: int) => { /* lambda body */ })(7) 2524 2525.. index:: 2526 expression 2527 coroutine 2528 launch 2529 function call expression 2530 lambda 2531 launch expression 2532 2533The result of the launch expression is of type ``Promise<T>``, where ``T`` is 2534the return type of the function being called: 2535 2536.. code-block:: typescript 2537 :linenos: 2538 2539 function foo(): int {} 2540 function bar() {} 2541 let resfoo = launch foo() 2542 let resbar = launch bar() 2543 2544In the example above the type of ``resfoo`` is ``Promise<int>``, and the 2545type of ``resbar`` is ``Promise<void>``. 2546 2547Similarly to |TS|, |LANG| supports the launching of a coroutine by calling 2548the function ``async`` (see :ref:`Async Functions`). No restrictions apply as 2549to from what scope to call the function ``async``: 2550 2551.. index:: 2552 launch expression 2553 return type 2554 function call 2555 coroutine 2556 async function 2557 restriction 2558 2559.. code-block:: typescript 2560 :linenos: 2561 2562 async function foo(): Promise<int> {} 2563 2564 // This will create and launch coroutine 2565 let resfoo = foo() 2566 2567| 2568 2569.. _Awaiting a Coroutine: 2570 2571Awaiting a Coroutine 2572==================== 2573 2574.. meta: 2575 frontend_status: Done 2576 2577The ``await`` expressions are used while a previously launched coroutine 2578finishes and returns a value: 2579 2580.. code-block:: abnf 2581 2582 awaitExpression: 2583 'await' expression 2584 ; 2585 2586A :index:`compile-time error` occurs if the expression type is not ``Promise<T>``. 2587 2588.. index:: 2589 expression await 2590 launch 2591 coroutine 2592 expression type 2593 2594.. code-block:: typescript 2595 :linenos: 2596 2597 let promise = launch (): int { return 1 } () 2598 console.log(await promise) // output: 1 2599 2600If the coroutine result must be ignored, then the expression statement 2601``await`` is used: 2602 2603.. code-block:: typescript 2604 :linenos: 2605 2606 function foo() { /* do something */ } 2607 let promise = launch foo() 2608 await promise 2609 2610The ``await`` cannot return ``Promise<T>`` or union type that contains 2611``Promise<T>``. If the actual type argument of ``T`` in ``Promise<T>`` contains 2612``Promise``, then the compiler eliminates any such usage. 2613 2614Return types of ``await`` expressions are represented in the example below: 2615 2616.. code-block:: typescript 2617 :linenos: 2618 2619 // if p has type Promise<Promise<string>>, 2620 // await p returns string 2621 let x : string = await p; 2622 2623 // if p2 has type Promise<Promise<string> | number>, 2624 // await p2 returns string | number 2625 let y : string | number = await p2; 2626 2627 // if p3 has type Promise<string>|Promise<number>, 2628 // await p2 returns string | number 2629 let z : string | number = await p3; 2630 2631.. index:: 2632 coroutine 2633 expression statement 2634 union type 2635 type argument 2636 await expression 2637 2638| 2639 2640.. _Promise<T> Class: 2641 2642``Promise<T>`` Class 2643==================== 2644 2645.. meta: 2646 frontend_status: Done 2647 2648The class ``Promise<T>`` represents the values returned by launch expressions 2649(see :ref:`Create and Launch a Coroutine`) and dynamic import expressions (see 2650:ref:`Dynamic Import Expression`). It belongs to the core packages of the 2651standard library (see :ref:`Standard Library`), and can be used without 2652any qualification. 2653 2654The methods are used as follows: 2655 2656- ``then`` takes two arguments (the first argument is the callback used if the 2657 promise is fulfilled, and the second if it is rejected), and returns 2658 ``Promise<U>``. 2659 2660.. index:: 2661 class 2662 value 2663 launch expression 2664 import expression 2665 argument 2666 callback 2667 package 2668 standard library 2669 method 2670 2671.. code-block:: typescript 2672 2673 Promise<U> Promise<T>::then<U>(fulfilCallback : 2674 function 2675 <T>(val: T) : Promise<U>, rejectCallback : (err: Object) 2676 : Promise<U>) 2677 2678- ``catch`` is the alias for ``Promise<T>.then<U>((value: T) : U => {}``, ``onRejected)``. 2679 2680.. code-block-meta: 2681 2682.. code-block:: typescript 2683 2684 Promise<U> Promise<T>::catch<U>(rejectCallback : (err: 2685 Object) : Promise<U>) 2686 2687- ``finally`` takes one argument (the callback called after ``promise`` is 2688 either fulfilled or rejected) and returns ``Promise<T>``. 2689 2690.. index:: 2691 alias 2692 callback 2693 call 2694 2695.. code-block:: typescript 2696 2697 Promise<U> Promise<T>::finally<U>(finallyCallback : ( 2698 Object: 2699 T) : Promise<U>) 2700 2701| 2702 2703.. _Structured Coroutines: 2704 2705Structured Coroutines 2706===================== 2707 2708.. meta: 2709 frontend_status: None 2710 2711| 2712 2713.. _Channels Classes: 2714 2715Channels Classes 2716================ 2717 2718.. meta: 2719 frontend_status: None 2720 2721*Channels* are used to send data between coroutines. 2722 2723*Channels classes* are a part of the coroutine-related package of the 2724standard library (see :ref:`Standard Library`). 2725 2726.. index:: 2727 channel class 2728 coroutine 2729 package 2730 2731| 2732 2733Async Functions and Methods 2734*************************** 2735 2736.. meta: 2737 frontend_status: Done 2738 2739| 2740 2741.. _Async Functions: 2742 2743``Async`` Functions 2744=================== 2745 2746.. meta: 2747 frontend_status: Done 2748 2749``Async`` functions are implicit coroutines that can be called as regular 2750functions. ``Async`` functions can be neither ``abstract`` nor ``native``. 2751 2752The return type of an ``async`` function must be ``Promise<T>`` (see 2753:ref:`Promise<T> Class`). Returning values of types ``Promise<T>`` and ``T`` 2754from ``async`` functions is allowed. 2755 2756Using return statement without an expression is allowed if the return type 2757is ``Promise<void>``. 2758*No-argument* return statement can be added implicitly as the last statement 2759of the function body if there is no explicit return statement in a function 2760with the return ``Promise<void>``. 2761 2762**Note**: Using type ``Promise<void>`` is not recommended as this type is 2763supported for the sake of backward |TS| compatibility only. 2764 2765.. index:: 2766 function async 2767 coroutine 2768 return type 2769 function body 2770 backward compatibility 2771 annotation 2772 no-argument return statement 2773 async function 2774 return statement 2775 compatibility 2776 2777| 2778 2779.. _Experimental Async Methods: 2780 2781Experimental ``Async`` Methods 2782============================== 2783 2784.. meta: 2785 frontend_status: Done 2786 2787The method ``async`` is an implicit coroutine that can be called as a regular 2788method. ``Async`` methods can be neither ``abstract`` nor ``native``. 2789 2790The return type of an ``async`` method must be ``Promise<T>`` (see 2791:ref:`Promise<T> Class`). Returning values of types ``Promise<T>`` and *T* from 2792``async`` methods is allowed. 2793 2794Using return statement without an expression is allowed if the return type 2795is ``Promise<void>``. 2796*No-argument* return statement can be added implicitly as the last statement 2797of the methods body if there is no explicit return statement in a method 2798with return type ``Promise<void>``. 2799 2800**Note**: Using this annotation is not recommended as this type of methods 2801is supported for the sake of backward |TS| compatibility only. 2802 2803.. index:: 2804 async method 2805 coroutine 2806 return type 2807 function body 2808 compatibility 2809 no-argument return statement 2810 annotation 2811 abstract method 2812 native method 2813 2814| 2815 2816.. _DynamicObject Type: 2817 2818DynamicObject Type 2819****************** 2820 2821.. meta: 2822 frontend_status: Partly 2823 2824The interface ``DynamicObject`` is used to provide seamless interoperability 2825with dynamic languages (e.g., |JS| and |TS|), and to support advanced 2826language features such as *dynamic import* (see :ref:`Dynamic Import Expression`). 2827 2828This interface (defined in :ref:`Standard Library`) is common for a set of 2829wrappers (also defined in :ref:`Standard Library`) that provide access to 2830underlying objects. 2831 2832An instance of ``DynamicObject`` cannot be created directly. Only an 2833instance of a specific wrapper object can be instantiated. For example, a 2834*dynamic import* expression (see :ref:`Dynamic Import Expression`) can produce 2835an instance of the dynamic object implementation class that wraps an object 2836containing exported entities of an imported module. 2837 2838``DynamicObject`` is a predefined type. The following operations applied to an 2839object of type ``DynamicObject`` are handled by the compiler in a special manner: 2840 2841- Field access; 2842- Method call; 2843- Indexing access; 2844- New; and 2845- Cast. 2846 2847.. index:: 2848 interface 2849 interoperability 2850 dynamic import 2851 interface 2852 wrapper 2853 access 2854 underlying object 2855 instantiation 2856 export 2857 entity 2858 import 2859 predefined type 2860 field access 2861 indexing access 2862 method call 2863 cast 2864 2865| 2866 2867.. _DynamicObject Field Access: 2868 2869``DynamicObject`` Field Access 2870============================== 2871 2872.. meta: 2873 frontend_status: Partly 2874 todo: now it supports only JSValue, need to add full abstract support 2875 2876The field access expression *D.F*, where *D* is of type ``DynamicObject``, 2877is handled as an access to a property of an underlying object. 2878 2879If the value of a field access is used, then it is wrapped in the instance of 2880``DynamicObject``, since the actual type of the field is not known at compile 2881time. 2882 2883.. code-block:: typescript 2884 :linenos: 2885 2886 function foo(d: DynamicObject) { 2887 console.log(d.f1) // access of the property named "f1" of underlying object 2888 d.f1 = 5 // set a value of the property named "f1" 2889 let y = d.f1 // 'y' is of type DynamicObject 2890 } 2891 2892The wrapper can raise an error if: 2893 2894- No property with the specified name exists in the underlying object; or 2895- The field access is in the right-hand side of the assignment, and the 2896 type of the assigned value is not compatible with the type of the property 2897 (see :ref:`Type Compatibility`). 2898 2899.. index:: 2900 wrapper 2901 dynamic import 2902 underlying object 2903 field access 2904 field access expression 2905 compile time 2906 property 2907 instance 2908 assignment 2909 assigned value 2910 2911 2912| 2913 2914.. _DynamicObject Method Call: 2915 2916``DynamicObject`` Method Call 2917============================= 2918 2919.. meta: 2920 frontend_status: Partly 2921 todo: now it supports only JSValue, need to add full abstract support 2922 2923The method call expression *D.F(arguments)*, where *D* is of type 2924``DynamicObject``, is handled as a call of the instance method of an 2925underlying object. 2926 2927If the result of a method call is used, then it is wrapped in the instance 2928of ``DynamicObject``, since the actual type of the returned value is not known 2929at compile time. 2930 2931.. code-block:: typescript 2932 :linenos: 2933 2934 function foo(d: DynamicObject) { 2935 d.foo() // call of a method "foo" of underlying object 2936 let y = d.goo() // 'y' is of type DynamicObject 2937 } 2938 2939The wrapper must raise an error if: 2940 2941- No method with the specified name exists in the underlying object; or 2942- The signature of the method is not compatible with the types of the 2943 call arguments. 2944 2945.. index:: 2946 DynamicObject 2947 wrapper 2948 method 2949 dynamic import 2950 field access 2951 property 2952 instance 2953 method 2954 2955| 2956 2957.. _DynamicObject Indexing Access: 2958 2959``DynamicObject`` Indexing Access 2960================================= 2961 2962.. meta: 2963 frontend_status: Partly 2964 todo: now it supports only JSValue, need to add full abstract support 2965 2966The indexing access expression *D[index]*, where *D* is of type 2967``DynamicObject``, is handled as an indexing access to an underlying object. 2968 2969 2970.. code-block-meta: 2971 2972.. code-block:: typescript 2973 :linenos: 2974 2975 function foo(d: DynamicObject) { 2976 let x = d[0] 2977 } 2978 2979The wrapper must raise an error if: 2980 2981- The indexing access is not supported by the underlying object; 2982- The type of the *index* expression is not supported by the underlying object. 2983 2984.. index:: 2985 indexing access expression 2986 index expression 2987 wrapper 2988 access 2989 underlying object 2990 2991| 2992 2993.. _DynamicObject New Expression: 2994 2995``DynamicObject`` New Expression 2996================================ 2997 2998.. meta: 2999 frontend_status: Partly 3000 todo: now it supports only JSValue, need to add full abstract support 3001 3002The new expression *new D(arguments)* (see :ref:`New Expressions`), where 3003*D* is of type ``DynamicObject``, is handled as a new expression (constructor 3004call) applied to the underlying object. 3005 3006The result of the expression is wrapped in an instance of ``DynamicObject``, 3007as the actual type of the returned value is not known at compile time. 3008 3009.. code-block:: typescript 3010 :linenos: 3011 3012 function foo(d: DynamicObject) { 3013 let x = new d() 3014 } 3015 3016The wrapper must raise an error if: 3017 3018- A new expression is not supported by the underlying object; or 3019- The signature of the constructor of the underlying object is not compatible 3020 with the types of call arguments. 3021 3022.. index:: 3023 expression 3024 constructor call 3025 constructor 3026 wrapper 3027 returned value 3028 compatibility 3029 call argument 3030 property 3031 instance 3032 3033| 3034 3035.. _DynamicObject Cast Expression: 3036 3037``DynamicObject`` Cast Expression 3038================================= 3039 3040.. meta: 3041 frontend_status: None 3042 3043The cast expression *D as T* (see :ref:`Cast Expressions`), where *D* is of 3044type ``DynamicObject``, is handled as an attempt to cast the underlying object 3045to a static type ``T``. 3046 3047A :index:`compile-time error` occurs if ``T`` is not a class or interface type. 3048 3049The result of a cast expression is an instance of type ``T``. 3050 3051.. code-block:: typescript 3052 :linenos: 3053 3054 interface I { 3055 bar() 3056 } 3057 3058 function foo(d: DynamicObject) { 3059 let x = d as I 3060 x.bar() // a call of interface method (not dynamic) 3061 } 3062 3063The wrapper must raise an error if an underlying object cannot be converted 3064to the target type specified by the cast operator. 3065 3066.. index:: 3067 wrapper 3068 underlying object 3069 cast expression 3070 interface type 3071 cast expression 3072 instance 3073 type 3074 conversion 3075 target type 3076 cast operator 3077 3078| 3079 3080.. _Packages: 3081 3082Packages 3083******** 3084 3085.. meta: 3086 frontend_status: Partly 3087 todo: Implement compiling a package module as a single compilation unit - #16267 3088 3089One or more *package modules* form a package: 3090 3091.. code-block:: abnf 3092 3093 packageDeclaration: 3094 packageModule+ 3095 ; 3096 3097*Packages* are stored in a file system or a database (see 3098:ref:`Compilation Units in Host System`). 3099 3100A *package* can consist of several package modules if all such modules 3101have the same *package header*: 3102 3103.. index:: 3104 package module 3105 package 3106 file system 3107 database 3108 package header 3109 module 3110 3111.. code-block:: abnf 3112 3113 packageModule: 3114 packageHeader packageModuleDeclaration 3115 ; 3116 3117 packageHeader: 3118 'package' qualifiedName 3119 ; 3120 3121 packageModuleDeclaration: 3122 importDirective* packageTopDeclaration* 3123 ; 3124 3125 packageTopDeclaration: 3126 topDeclaration | packageInitializer 3127 ; 3128 3129A :index:`compile-time error` occurs if: 3130 3131- A *package module* contains no package header; or 3132- Package headers of two package modules in the same package have 3133 different identifiers. 3134 3135Every *package module* can directly use all exported entities from the core 3136packages of the standard library (see :ref:`Standard Library Usage`). 3137 3138A *package module* can directly access all top-level entities declared in all 3139modules that constitute the package. 3140 3141.. index:: 3142 package module 3143 package header 3144 package 3145 identifier 3146 core package 3147 import 3148 exported entity 3149 access 3150 top-level entity 3151 module 3152 standard library 3153 simple name 3154 3155| 3156 3157.. _Internal Access Modifier Experimental: 3158 3159Internal Access Modifier 3160======================== 3161 3162.. meta: 3163 frontend_status: Partly 3164 todo: Implement in libpandafile, implement semantic, now it is parsed and ignored - #16088 3165 3166The modifier ``internal`` indicates that a class member, a constructor, or 3167an interface member is accessible (see :ref:`Accessible`) within its 3168compilation unit only. If the compilation unit is a package (see 3169:ref:`Packages`), then ``internal`` members can be used in any 3170*package module*. If the compilation unit is a separate module (see 3171:ref:`Separate Modules`), then ``internal`` members can be used within this 3172module. 3173 3174.. index:: 3175 modifier 3176 access modifier 3177 accessibility 3178 interface 3179 class member 3180 constructor 3181 access 3182 package module 3183 module 3184 3185.. code-block:: typescript 3186 :linenos: 3187 3188 class C { 3189 internal count: int 3190 getCount(): int { 3191 return this.count // ok 3192 } 3193 } 3194 3195 function increment(c: C) { 3196 c.count++ // ok 3197 } 3198 3199.. index:: 3200 member 3201 constructor 3202 internal modifier 3203 access 3204 3205| 3206 3207.. _Package Initializer: 3208 3209Package Initializer 3210=================== 3211 3212.. meta: 3213 frontend_status: None 3214 3215Among all *package modules* there can be one to contain a code that performs 3216initialization actions (e.g., setting initial values for variables across all 3217package modules) as described in detail in :ref:`Compilation Unit Initialization`. 3218The appropriate syntax is presented below: 3219 3220.. index:: 3221 package initializer 3222 package module 3223 initialization 3224 compilation unit 3225 variable 3226 package initializer 3227 3228.. code-block:: abnf 3229 3230 packageInitializer: 3231 'static' block 3232 ; 3233 3234A :index:`compile-time error` occurs if a package contains more than one 3235*package initializer*. 3236 3237| 3238 3239.. _Import and Overloading of Function Names: 3240 3241Import and Overloading of Function Names 3242======================================== 3243 3244.. meta: 3245 frontend_status: Done 3246 3247While importing functions, the following situations can occur: 3248 3249- Different imported functions have the same name but different signatures, or 3250 a function (functions) of the current module and an imported function 3251 (functions) have the same name but different signatures. This situation is 3252 *overloading*. All such functions are accessible (see :ref:`Accessible`). 3253 3254- A function (functions) of the current module and an imported function 3255 (functions) have the same name and overload-equivalent signature (see 3256 :ref:`Overload-Equivalent Signatures`). This situation is a 3257 :index:`compile-time error` as declarations are duplicated. Qualified import 3258 or alias in import can be used to access the imported entity. 3259 3260.. index:: 3261 import 3262 function 3263 overloading 3264 function name 3265 function 3266 imported function 3267 signature 3268 module 3269 access 3270 accessibility 3271 3272The two situations are illustrated by the examples below: 3273 3274.. code-block-meta: 3275 skip 3276 3277.. code-block:: typescript 3278 :linenos: 3279 3280 // Overloading case 3281 package P1 3282 function foo(p: int) {} 3283 3284 package P2 3285 function foo(p: string) {} 3286 3287 // Main module 3288 import {foo} from "path_to_file_with_P1" 3289 import {foo} from "path_to_file_with_P2" 3290 3291 function foo (p: double) {} 3292 3293 function main() { 3294 foo(5) // Call to P1.foo(int) 3295 foo("A string") // Call to P2.foo(string) 3296 foo(3.141592653589) // Call to local foo(double) 3297 } 3298 3299 3300 // Declaration duplication case 3301 package P1 3302 function foo() {} 3303 package P2 3304 function foo() {} 3305 // Main program 3306 import {foo} from "path_to_file_with_P1" 3307 import {foo} from "path_to_file_with_P2" /* Error: duplicating 3308 declarations imported*/ 3309 function foo() {} /* Error: duplicating declaration identified 3310 */ 3311 function main() { 3312 foo() // Error: ambiguous function call 3313 // But not a call to local foo() 3314 // foo() from P1 and foo() from P2 are not accessible 3315 } 3316 3317| 3318 3319.. _Generics Experimental: 3320 3321Generics Experimental 3322********************* 3323 3324| 3325 3326.. _NonNullish Type Parameter: 3327 3328NonNullish Type Parameter 3329========================= 3330 3331.. meta: 3332 frontend_status: None 3333 3334If some generic class has a type parameter with nullish union type constraint, 3335then special syntax for type annotation can be used to get a non-nullish 3336version of the type parameter variable. The example below illustrates this 3337possibility: 3338 3339.. index:: 3340 generic class 3341 type parameter 3342 nullish union type 3343 constraint 3344 annotation 3345 non-nullish type 3346 variable 3347 parameter 3348 3349.. code-block:: typescript 3350 :linenos: 3351 3352 class A<T> { // in fact it extends Object|null|undefined 3353 foo (p: T): T! { // foo returns non-nullish value of p 3354 return p! 3355 } 3356 } 3357 3358 class B<T extends SomeType | null> { 3359 foo (p: T): T! { // foo returns non-nullish value of p 3360 return p! 3361 } 3362 } 3363 3364 class C<T extends SomeType | undefined> { 3365 foo (p: T): T! { // foo returns non-nullish value of p 3366 return p! 3367 } 3368 } 3369 3370 let a = new A<Object> 3371 let b = new B<SomeType> 3372 let c = new C<SomeType> 3373 3374 let result: Object = new Object // Type of result is non-nullish ! 3375 result = a.foo(result) 3376 result = b.foo(new SomeType) 3377 result = c.foo(new SomeType) 3378 3379 // All such assignments are type-valid as well 3380 result = a.foo(void) // void! => never 3381 result = b.foo(null) // null! => never 3382 result = c.foo(undefined) // undefined! => never 3383 3384 3385.. raw:: pdf 3386 3387 PageBreak 3388