1.. 2 Copyright (c) 2021-2025 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.. _Semantic Rules: 14 15Semantic Rules 16############## 17 18.. meta: 19 frontend_status: Done 20 21This Chapter contains semantic rules to be used throughout this Specification 22document. The description of the rules is more or less informal. Some details 23are omitted to simplify the understanding. 24 25.. index:: 26 semantic rule 27 28| 29 30.. _Semantic Essentials: 31 32Semantic Essentials 33******************* 34 35The section gives a brief introduction to the major semantic terms 36and their usage in several contexts. 37 38| 39 40.. _Type of Standalone Expression: 41 42Type of Standalone Expression 43============================= 44 45*Standalone expression* (see :ref:`Type of Expression`) is an expression for 46which no target type is expected in its context. 47 48The type of a *standalone expression* is determined as follows: 49 50- In case of :ref:`Numeric Literals`, the type is the default type of a literal: 51 52 - Type of :ref:`Integer Literals` is ``int`` or ``long``; 53 - Type of :ref:`Floating-Point Literals` is ``double`` or ``float``. 54 55- In case of :ref:`Constant Expressions`, the type is inferred from operand 56 types and operations. 57 58- In case of an :ref:`Array Literal`, the type is inferred from the elements 59 (see :ref:`Array Type Inference from Types of Elements`). 60 61- Otherwise, a :index:`compile-time error` occurs. Specifically, 62 a :index:`compile-time error` occurs if an *object literal* is used 63 as a *standalone expression*. 64 65The situation is represented by the example below: 66 67.. code-block:: typescript 68 :linenos: 69 70 function foo() { 71 1 // type is 'int' 72 1.0 // type is 'number' 73 [1.0, 2.0] // type is number[] 74 [1, "aa"] // type is (int | string) 75 } 76 77| 78 79.. Specifics of Assignment-like Contexts: 80 81Specifics of Assignment-like Contexts 82===================================== 83 84*Assignment-like context* (see :ref:`Assignment-like Contexts`) can be 85considered as an assignment ``x = expr``, where ``x`` is a left-hand-side 86expression, and ``expr`` is a right-hand-side expression. E.g., there is an 87implicit assignment of ``expr`` to the formal parameter ``foo`` in the call 88``foo(expr)``, and implicit assignments to elements or properties in 89:ref:`Array Literal` and :ref:`Object Literal`. 90 91*Assignment-like context* is specific in that the type of a left-hand-side 92expression is known, but the type of a right-hand-side expression is not 93necessarily known in the context as follows: 94 95- If the type of a right-hand-side expression is known from the expression 96 itself, then the :ref:`Assignability` check is performed as in the example 97 below: 98 99.. code-block:: typescript 100 :linenos: 101 102 function foo(x: string, y: string) { 103 x = y // ok, assignability is checked 104 } 105 106- Otherwise, an attempt is made to apply the type of the left-hand-side 107 expression to the right-hand-side expression. A :index:`compile-time error` 108 occurs if the attempt fails as in the example below: 109 110.. code-block:: typescript 111 :linenos: 112 113 function foo(x: int, y: double[]) { 114 x = 1 // ok, type of '1' is inferred from type of 'x' 115 y = [1, 2] // ok, array literal is evaluated as [1.0, 2.0] 116 } 117 118| 119 120.. Specifics of Variable Initialization Context: 121 122Specifics of Variable Initialization Context 123============================================ 124 125If the variable or a constant declaration (see 126:ref:`Variable and Constant Declarations`) has an explicit type annotation, 127then the same rules as for *assignment-like contexts* apply. Otherwise, there 128are two cases for ``let x = expr`` (see :ref:`Type Inference from Initializer`) 129as follows: 130 131- The type of the right-hand-side expression is known from the expression 132 itself, then this type becomes the type of the variable as in the example 133 below: 134 135.. code-block:: typescript 136 :linenos: 137 138 function foo(x: int) { 139 let x = y // type of 'x' is 'int' 140 } 141 142- Otherwise, the type of ``expr`` is evaluated as type of a standalone 143 expression as in the example below: 144 145.. code-block:: typescript 146 :linenos: 147 148 function foo() { 149 let x = 1 // x is of type 'int' (default type of '1') 150 let y = [1, 2] // x is of type 'number[]' 151 } 152 153| 154 155.. _Specifics of Numeric Operator Contexts: 156 157Specifics of Numeric Operator Contexts 158====================================== 159 160Operands of unary and binary numeric expressions are widened to a larger numeric 161type. The minimum type is ``int``. Specifically, no arithmetic operator 162evaluates values of types ``byte`` and ``short`` without widening. Details of 163specific operators are discussed in corresponding sections of the Specification. 164 165| 166 167.. _Specifics of String Operator Contexts: 168 169Specifics of String Operator Contexts 170===================================== 171 172If one operand of the binary operator ‘`+`’ is of type ``string``, then the 173string conversion applies to another non-string operand to convert it to string 174(see :ref:`String Concatenation` and :ref:`String Operator Contexts`). 175 176| 177 178.. _Other Contexts: 179 180Other Contexts 181============== 182 183The only semantic rule for all other contexts, and specifically for 184:ref:`Overloading and Overriding`, is to use :ref:`Subtyping`. 185 186| 187 188.. _Specifics of Type Parameters: 189 190Specifics of Type Parameters 191============================ 192 193If the type of a left-hand-side expression in *assignment-like context* is a 194type parameter, then it provides no additional information for type inference 195even where a type parameter constraint is set. 196 197If the *target type* of an expression is a *type parameter*, then the type of 198the expression is inferred as the type of a *standalone expression*. 199 200The semantics is represented by the example below: 201 202.. code-block:: typescript 203 :linenos: 204 205 class C<T extends number> { 206 constructor (x: T) {} 207 } 208 209 new C(1) // compile-time error 210 211The type of '``1``' in the example above is inferred as ``int`` (default type of 212an integer literal). The expression is considered ``new C<int>(1)`` and causes 213a :index:`compile-time error` because ``int`` is not a subtype of ``number`` 214(type parameter constraint). 215 216Explicit type argument ``new C<number>(1)`` must be used to fix the code. 217 218| 219 220.. _Semantic Essentials Summary: 221 222Semantic Essentials Summary 223=========================== 224 225Major semantic terms are listed below: 226 227- :ref:`Type of Expression`; 228- :ref:`Assignment-like Contexts`; 229- :ref:`Type Inference from Initializer`; 230- :ref:`Numeric Operator Contexts`; 231- :ref:`String Operator Contexts`; 232- :ref:`Subtyping`; 233- :ref:`Assignability`; 234- :ref:`Overloading and Overriding`; 235- :ref:`Type Inference`. 236 237| 238 239.. _Subtyping: 240 241Subtyping 242********* 243 244.. meta: 245 frontend_status: Done 246 247*Subtype* relationship between types ``S`` and ``T``, where ``S`` is a 248subtype of ``T`` (recorded as ``S<:T``), means that any object of type 249``S`` can be safely used in any context to replace an object of type ``T``. 250The opposite relation (recorded as ``T:>S``) is called *supertype* relationship. 251Each type is its own subtype and supertype (``S<:S``). 252 253By the definition of ``S<:T``, type ``T`` belongs to the set of *supertypes* 254of type ``S``. The set of *supertypes* includes all *direct supertypes* 255(discussed in subsections), and all their respective *supertypes*. 256More formally speaking, the set is obtained by reflexive and transitive 257closure over the direct supertype relation. 258 259If the subtyping relation of two types is not defined in a section below, 260then such types are not related to each other. Specifically, two array types 261(resizable and fixed-size alike), and two tuple types are not related to each 262other, except where they are identical (see :ref:`Type Identity`). 263 264.. index:: 265 subtyping 266 subtype 267 closure 268 supertype 269 direct supertype 270 reflexive closure 271 transitive closure 272 array type 273 array 274 resizable array 275 fixed-size array 276 tuple type 277 type 278 279| 280 281.. _Subtyping for Classes and Interfaces: 282 283Subtyping for Classes and Interfaces 284==================================== 285 286.. meta: 287 frontend_status: Partly 288 289Terms *subclass*, *subinterface*, *superclass*, and *superinterface* are used 290when considering class or interface types. 291 292*Direct supertypes* of a non-generic class, or of the interface type ``C`` 293are **all** of the following: 294 295- Direct superclass of ``C`` (as mentioned in its extension clause, see 296 :ref:`Class Extension Clause`) or type ``Object`` if ``C`` has no extension 297 clause specified; 298 299- Direct superinterfaces of ``C`` (as mentioned in the implementation 300 clause of ``C``, see :ref:`Class Implementation Clause`); and 301 302- Class ``Object`` if ``C`` is an interface type with no direct superinterfaces 303 (see :ref:`Superinterfaces and Subinterfaces`). 304 305.. index:: 306 subclass 307 subinterface 308 superclass 309 superinterface 310 interface type 311 direct supertype 312 non-generic class 313 direct superclass 314 direct superinterface 315 implementation 316 non-generic class 317 extension clause 318 implementation clause 319 superinterface 320 Object 321 interface type 322 direct superinterface 323 class extension 324 subinterface 325 326*Direct supertypes* of the generic type ``C`` <``F``:sub:`1` ``,..., F``:sub:`n`> 327(for a generic class or interface type declaration ``C`` <``F``:sub:`1` ``,..., F``:sub:`n`> 328with *n*>0) are **all** of the following: 329 330- Direct superclass of ``C`` <``F``:sub:`1` ``,..., F``:sub:`n`>; 331 332- Direct superinterfaces of ``C`` <``F``:sub:`1` ``,..., F``:sub:`n`>, and 333 334- Type ``Object`` if ``C`` <``F``:sub:`1` ``,..., F``:sub:`n`> is a generic 335 interface type with no direct superinterfaces. 336 337The direct supertype of a type parameter is the type specified as the 338constraint of that type parameter. 339 340.. index:: 341 direct supertype 342 generic type 343 generic class 344 generic interface 345 interface type declaration 346 direct superinterface 347 type parameter 348 superclass 349 supertype 350 type 351 constraint 352 type parameter 353 superinterface 354 bound 355 Object 356 357| 358 359 360.. _Subtyping for Literal Types: 361 362Subtyping for Literal Types 363=========================== 364 365.. meta: 366 frontend_status: Done 367 368Any ``string`` literal type (see :ref:`Literal Types`) is *subtype* of type 369``string``. It affects overriding as shown in the example below: 370 371.. code-block:: typescript 372 :linenos: 373 374 class Base { 375 foo(p: "1"): string { return "42" } 376 } 377 class Derived extends Base { 378 override foo(p: string): "1" { return "1" } 379 } 380 // Type "1" <: string 381 382 let base: Base = new Derived 383 let result: string = base.foo("1") 384 /* Argument "1" (value) is compatible to type "1" and to type string in 385 the overridden method 386 Function result of type string accepts "1" (value) of literal type "1" 387 */ 388 389Literal type ``null`` (see :ref:`Literal Types`) is a subtype and a supertype to 390itself. Similarly, literal type ``undefined`` is a subtype and a supertype to 391itself. 392 393.. index:: 394 literal type 395 subtype 396 type string 397 overriding 398 supertype 399 string literal 400 null 401 undefined 402 literal type 403 404| 405 406.. _Subtyping for Union Types: 407 408Subtyping for Union Types 409========================= 410 411.. meta: 412 frontend_status: Done 413 414A union type ``U`` participates in subtyping relations 415(see :ref:`Subtyping`) in the following cases: 416 4171. Union type ``U`` (``U``:sub:`1` ``| ... | U``:sub:`n`) is a subtype of 418type ``T`` if each ``U``:sub:`i` is a subtype of ``T``. 419 420.. code-block:: typescript 421 :linenos: 422 423 let s1: "1" | "2" = "1" 424 let s2: string = s1 // ok 425 426 let a: string | number | boolean = "abc" 427 let b: string | number = 42 428 a = b // OK 429 b = a // compile-time error, boolean is absent is 'b' 430 431 class Base {} 432 class Derived1 extends Base {} 433 class Derived2 extends Base {} 434 435 let x: Base = ... 436 let y: Derived1 | Derived2 = ... 437 438 x = y // OK, both Derived1 and Derived2 are subtypes of Base 439 y = x // compile-time error 440 441 let x: Base | string = ... 442 let y: Derived1 | string ... 443 x = y // OK, Derived1 is subtype of Base 444 y = x // compile-time error 445 446.. index:: 447 union type 448 subtyping 449 subtype 450 type 451 4522. Type ``T`` is a subtype of union type ``U`` 453(``U``:sub:`1` ``| ... | U``:sub:`n`) if for some ``i`` 454``T`` is a subtype of ``U``:sub:`i`. 455 456.. code-block:: typescript 457 :linenos: 458 459 let u: number | string = 1 // ok 460 u = "aa" // ok 461 u = 1.0 // ok, 1.0 is of type 'number' (double) 462 u = 1 // compile-time error, type 'int' is not a subtype of 'number' 463 u = true // compile-time error 464 465**Note**. If union type normalization produces a single type, then this type 466is used instead of the initial set of union types. This concept is represented 467by the example below: 468 469.. index:: 470 union type 471 normalization 472 subtype 473 474.. code-block:: typescript 475 :linenos: 476 477 let u: "abc" | "cde" | string // type of 'u' is string 478 479| 480 481.. _Subtyping for Function Types: 482 483Subtyping for Function Types 484============================ 485 486.. meta: 487 frontend_status: Done 488 489Function type ``F`` with parameters ``FP``:sub:`1` ``, ... , FP``:sub:`m` 490and return type ``FR`` is a *subtype* of function type ``S`` with parameters 491``SP``:sub:`1` ``, ... , SP``:sub:`n` and return type ``SR`` if **all** of the 492following conditions are met: 493 494- ``m <= n`` 495 496- for each ``i <= m`` 497 498 - Parameter type of ``SP``:sub:`i` is a subtype of 499 parameter type of ``FP``:sub:`i` (contravariance), and 500 501 - ``FP``:sub:`i` is a rest parameter if ``SP``:sub:`i` is a rest parameter. 502 - ``FP``:sub:`i` is an optional parameter if ``SP``:sub:`i` is an optional 503 parameter. 504 505- ``FR`` can be any type if ``SR`` is type ``void``. Otherwise, the resultant 506 type ``FR`` is a subtype of ``SR`` (covariance). 507 508.. index:: 509 function type 510 subtype 511 parameter type 512 contravariance 513 rest parameter 514 parameter 515 covariance 516 return type 517 518.. code-block:: typescript 519 :linenos: 520 521 class Base {} 522 class Derived extends Base {} 523 524 function check( 525 bb: (p: Base) => Base, 526 bd: (p: Base) => Derived, 527 db: (p: Derived) => Base, 528 dd: (p: Derived) => Derived 529 ) { 530 bb = bd 531 /* OK: identical parameter types, and covariant return type */ 532 bb = dd 533 /* Compile-time error: parameter type are not contravariant */ 534 db = bd 535 /* OK: contravariant parameter types, and covariant return type */ 536 537 let f: (p: Base, n: number) => Base = bb 538 /* OK: subtype has less parameters */ 539 540 let g: () => Base = bb 541 /* Compile-time error: too less parameters */ 542 543 let h: (p: Base) => void = bb 544 /* OK: result type of supertype is void */ 545 } 546 547.. index:: 548 parameter type 549 covariance 550 contravariance 551 covariant return type 552 contravariant return type 553 supertype 554 parameter 555 556| 557 558.. _Type Identity: 559 560Type Identity 561************* 562 563.. meta: 564 frontend_status: Done 565 566*Identity* relation between two types means that the types are 567indistinguishable. Identity relation is symmetric and transitive. 568Identity relation for types ``A`` and ``B`` is defined as follows: 569 570- Array types ``A`` = ``T1[]`` and ``B`` = ``Array<T2>`` are identical 571 if ``T1`` and ``T2`` are identical. 572 573- Tuple types ``A`` = [``T``:sub:`1`, ``T``:sub:`2`, ``...``, ``T``:sub:`n`] and 574 ``B`` = [``U``:sub:`1`, ``U``:sub:`2`, ``...``, ``U``:sub:`m`] 575 are identical if the following conditions are met: 576 577 - ``n`` is equal to ``m``, i.e., the types have the same number of elements; 578 - Every *T*:sub:`i` is identical to *U*:sub:`i` for any *i* in ``1 .. n``. 579 580- Union types ``A`` = ``T``:sub:`1` | ``T``:sub:`2` | ``...`` | ``T``:sub:`n` and 581 ``B`` = ``U``:sub:`1` | ``U``:sub:`2` | ``...`` | ``U``:sub:`m` 582 are identical if the following conditions are met: 583 584 - ``n`` is equal to ``m``, i.e., the types have the same number of elements; 585 - *U*:sub:`i` in ``U`` undergoes a permutation after which every *T*:sub:`i` 586 is identical to *U*:sub:`i` for any *i* in ``1 .. n``. 587 588- Types ``A`` and ``B`` are identical if ``A`` is a subtype of ``B`` (``A<:B``), 589 and ``B`` is at the same time a subtype of ``A`` (``A:>B``). 590 591**Note.** :ref:`Type Alias Declaration` creates no new type but only a new 592name for the existing type. An alias is indistinguishable from its base type. 593 594.. index:: 595 type identity 596 identity 597 indistinguishable type 598 array type 599 tuple type 600 union type 601 subtype 602 type 603 type alias 604 declaration 605 base type 606 607| 608 609.. _Assignability: 610 611Assignability 612************* 613 614.. meta: 615 frontend_status: Done 616 617Type ``T``:sub:`1` is assignable to type ``T``:sub:`2` if: 618 619- ``T``:sub:`1` is type ``never`` and ``T``:sub:`2` is any other type; 620 621- ``T``:sub:`1` is identical to ``T``:sub:`2` (see :ref:`Type Identity`); 622 623- ``T``:sub:`1` is a subtype of ``T``:sub:`2` (see :ref:`Subtyping`); or 624 625- *Implicit conversion* (see :ref:`Implicit Conversions`) is present that 626 allows converting a value of type ``T``:sub:`1` to type ``T``:sub:`2`. 627 628 629*Assignability* relationship is asymmetric, i.e., that ``T``:sub:`1` 630is assignable to ``T``:sub:`2` does not imply that ``T``:sub:`2` is 631assignable to type ``T``:sub:`1`. 632 633.. index:: 634 assignability 635 type 636 type identity 637 subtyping 638 conversion 639 implicit conversion 640 asymmetric relationship 641 642| 643 644.. _Invariance, Covariance and Contravariance: 645 646Invariance, Covariance and Contravariance 647***************************************** 648 649.. meta: 650 frontend_status: Done 651 652*Variance* is how subtyping between types relates to subtyping between 653derived types, including generic types (See :ref:`Generics`), member 654signatures of generic types (type of parameters, return type), 655and overriding entities (See :ref:`Override-Compatible Signatures`). 656Variance can be of three kinds: 657 658- Covariance, 659- Contravariance, and 660- Invariance. 661 662.. index:: 663 variance 664 subtyping 665 type 666 subtyping 667 derived type 668 generic type 669 generic 670 signature 671 type parameter 672 overriding entity 673 override-compatible signature 674 parameter 675 return type 676 variance 677 invariance 678 covariance 679 contravariance 680 681*Covariance* means it is possible to use a type which is more specific than 682originally specified. 683 684.. index:: 685 covariance 686 687*Contravariance* means it is possible to use a type which is more general than 688originally specified. 689 690.. index:: 691 contravariance 692 693*Invariance* means it is only possible to use the original type, i.e., there is 694no subtyping for derived types. 695 696.. index:: 697 invariance 698 699The examples below illustrate valid and invalid usages of variance. 700If class ``Base`` is defined as follows: 701 702.. index:: 703 variance 704 base class 705 706.. code-block:: typescript 707 :linenos: 708 709 class Base { 710 method_one(p: Base): Base {} 711 method_two(p: Derived): Base {} 712 method_three(p: Derived): Derived {} 713 } 714 715---then the code below is valid: 716 717.. code-block:: typescript 718 :linenos: 719 720 class Derived extends Base { 721 // invariance: parameter type and return type are unchanged 722 override method_one(p: Base): Base {} 723 724 // covariance for the return type: Derived is a subtype of Base 725 override method_two(p: Derived): Derived {} 726 727 // contravariance for parameter types: Base is a supertype for Derived 728 override method_three(p: Base): Derived {} 729 } 730 731.. index:: 732 variance 733 subtype 734 base 735 overriding 736 method 737 738On the contrary, the following code causes compile-time errors: 739 740.. code-block-meta: 741 expect-cte 742 743.. code-block:: typescript 744 :linenos: 745 746 class Derived extends Base { 747 748 // covariance for parameter types is prohibited 749 override method_one(p: Derived): Base {} 750 751 // contravariance for the return type is prohibited 752 override method_tree(p: Derived): Base {} 753 } 754 755| 756 757.. _Compatibility of Call Arguments: 758 759Compatibility of Call Arguments 760******************************* 761 762.. meta: 763 frontend_status: Done 764 765 766The following semantic checks must be performed to arguments from the left to 767the right when checking the validity of any function, method, constructor, or 768lambda call: 769 770**Step 1**: All arguments in the form of spread expression (see 771:ref:`spread Expression`) are to be linearized recursively to enusre that 772no spread expression is left at the call site. 773 774**Step 2**: The following checks are performed on all arguments from left to 775right, starting from ``arg_pos`` = 1 and ``par_pos`` = 1: 776 777 if parameter at position ``par_pos`` is of non-rest form, then 778 779 if `T`:sub:`arg_pos` <: `T`:sub:`par_pos`, then increment ``arg_pos`` and ``par_pos`` 780 else a :index:`compile-time error` occurs, exit Step 2 781 782 else // parameter is of rest form (see :ref:`Rest Parameter`) 783 784 if parameter is of rest_array_form, then 785 786 if `T`:sub:`arg_pos` <: `T`:sub:`rest_array_type`, then increment ``arg_pos`` 787 else increment ``par_pos`` 788 789 else // parameter is of rest_tuple_form 790 791 for `rest_tuple_pos` in 1 .. rest_tuple_types.count do 792 793 if `T`:sub:`arg_pos` <: `T`:sub:`rest_tuple_pos`, then increment ``arg_pos`` and `rest_tuple_pos` 794 else if rest_tuple_pos < rest_tuple_types.count, then increment ``rest_tuple_pos`` 795 else a :index:`compile-time error` occurs, exit Step 2 796 797 end 798 increment ``par_pos`` 799 800 end 801 802 end 803 804.. index:: 805 assignability 806 compatibility 807 semantic check 808 function call 809 method call 810 constructor call 811 function 812 method 813 constructor 814 rest parameter 815 parameter 816 spread operator 817 spread expression 818 array 819 tuple 820 argument type 821 expression 822 operator 823 assignable type 824 increment 825 array type 826 rest parameter 827 828The examples below represent the checks: 829 830.. code-block:: typescript 831 :linenos: 832 833 call (...[1, "str", true], ...[ ...123]) // Initial call form 834 835 call (1, "str", true, 123) // To be unfoled into the form with no spread expressions 836 837 838 839 function foo1 (p: Object) {} 840 foo1 (1) // Type of '1' must be assignable to 'Object' 841 // p becomes 1 842 843 function foo2 (...p: Object[]) {} 844 foo2 (1, "111") // Types of '1' and "111" must be assignable to 'Object' 845 // p becomes array [1, "111"] 846 847 function foo31 (...p: (number|string)[]) {} 848 foo31 (...[1, "111"]) // Type of array literal [1, "111"] must be assignable to (number|string)[] 849 // p becomes array [1, "111"] 850 851 function foo32 (...p: [number, string]) {} 852 foo32 (...[1, "111"]) // Types of '1' and "111" must be assignable to 'number' and 'string' accordingly 853 // p becomes tuple [1, "111"] 854 855 function foo4 (...p: number[]) {} 856 foo4 (1, ...[2, 3]) // 857 // p becomes array [1, 2, 3] 858 859 function foo5 (p1: number, ...p2: number[]) {} 860 foo5 (...[1, 2, 3]) // 861 // p1 becomes 1, p2 becomes array [2, 3] 862 863 864 865 866.. index:: 867 assignable type 868 Object 869 string 870 array 871 872| 873 874 875.. _Type Inference: 876 877Type Inference 878************** 879 880.. meta: 881 frontend_status: Done 882 883|LANG| supports strong typing but allows not to burden a programmer with the 884task of specifying type annotations everywhere. A smart compiler can infer 885types of some entities and expressions from the surrounding context. 886This technique called *type inference* allows keeping type safety and 887program code readability, doing less typing, and focusing on business logic. 888Type inference is applied by the compiler in the following contexts: 889 890- :ref:`Type Inference for Integer Constant Expressions`; 891- Variable and constant declarations (see :ref:`Type Inference from Initializer`); 892- Implicit generic instantiations (see :ref:`Implicit Generic Instantiations`); 893- Function, method or lambda return type (see :ref:`Return Type Inference`); 894- Lambda expression parameter type (see :ref:`Lambda Signature`); 895- Array literal type inference (see :ref:`Array Literal Type Inference from Context`, 896 and :ref:`Array Type Inference from Types of Elements`); 897- Object literal type inference (see :ref:`Object Literal`); 898- Smart types (see :ref:`Smart Types`). 899 900.. index:: 901 strong typing 902 type annotation 903 smart compiler 904 type inference 905 entity 906 surrounding context 907 code readability 908 type safety 909 context 910 variable declaration 911 constant declaration 912 generic instantiation 913 function return type 914 function 915 method return type 916 method 917 return type 918 lambda expression 919 parameter type 920 array literal 921 Object literal 922 smart type 923 924| 925 926.. _Type Inference for Integer Constant Expressions: 927 928Type Inference for Integer Constant Expressions 929=============================================== 930 931For :ref:`Constant Expressions` of integer types 932the type of expression is first evaluated from the expression 933in the following way: 934 935- For an integer literal the type is the default type of the literal: 936 ``int`` or ``long`` (see :ref:`Integer Literals`); 937 938- For a named constant the type is specified in the constant declaration; 939 940- For an operator the result type is evaluated accoriding rules of 941 this operator; 942 943- For :ref:`Cast expression` type is specified in the expression 944 target type. 945 946If the evaluated result type is of an integer type, 947it can be inferred to smaller integer *target type* from the context, 948if the following conditions are met: 949 950#. The top-level expression is not a cast expression; 951 952#. The value of the expression fits into the range of the *target type*. 953 954The examples below illustrate valid and invalid narrowing. 955 956.. code-block-meta: 957 expect-cte: 958 959.. code-block:: typescript 960 :linenos: 961 962 let b: byte = 127 // ok, int -> byte narrowing 963 b = 64 + 63 // ok, int -> byte narrowing 964 b = 128 // compile-time-error, value is out of range 965 b = 1.0 // compile-time-error, floating-point value cannot be narrowed 966 b = 1 as short // // compile-time-error, cast expresion 967 968 let s: short = 32768 // compile-time-error, value is out of range 969 970.. index:: 971 narrowing 972 constant 973 constant expression 974 integer conversion 975 integer type 976 expression 977 conversion 978 type 979 value 980 981| 982 983.. _Smart Types: 984 985Smart Types 986=========== 987 988.. meta: 989 frontend_status: Partly 990 todo: implement a dataflow check for loops and try-catch blocks 991 992Data entities like local variables (see :ref:`Variable and Constant Declarations`) 993and parameters (see :ref:`Parameter List`), if not captured in a lambda body and 994modified by the lambda code, are subjected to *smart typing*. 995 996Every data entity has a static type, which is specified explicitly or 997inferred at the point of declaration. This type defines the set of operations 998that can be applied to the entity (namely, what methods can be called, and what 999other entities can be accessed if the entity acts as a receiver of the 1000operation): 1001 1002.. code-block:: typescript 1003 :linenos: 1004 1005 let a = new Object 1006 a.toString() // entity 'a' has method toString() 1007 1008.. index:: 1009 smart type 1010 data entity 1011 variable 1012 parameter 1013 class variable 1014 local variable 1015 smart typing 1016 lambda code 1017 function 1018 method 1019 static type 1020 inferred type 1021 receiver 1022 access 1023 declaration 1024 1025If an entity is class type (see :ref:`Classes`), interface type (see 1026:ref:`Interfaces`), or union type (see :ref:`Union Types`), then the compiler 1027can narrow (smart cast) a static type to a more precise type (smart type), and 1028allow operations that are specific to the type so narrowed: 1029 1030.. code-block:: typescript 1031 :linenos: 1032 1033 function boo() { 1034 let a: number | string = 42 1035 a++ /* Here we know for sure that type of 'a' is number and number-specific 1036 operations are type-safe */ 1037 } 1038 1039 class Base {} 1040 class Derived extends Base { method () {} } 1041 function goo() { 1042 let b: Base = new Derived 1043 b.method () /* Here we know for sure that type of 'b' is Derived and Derived-specific 1044 operations can be applied in type-safe way */ 1045 } 1046 1047Other examples are explicit calls to ``instanceof`` 1048(see :ref:`InstanceOf Expression`) or checks against ``null`` 1049(see :ref:`Reference Equality`) as part of ``if`` statements 1050(see :ref:`if Statements`) or conditional expressions 1051(see :ref:`Conditional Expressions`): 1052 1053.. code-block:: typescript 1054 :linenos: 1055 1056 function foo (b: Base, d: Derived|null) { 1057 if (b instanceof Derived) { 1058 b.method() 1059 } 1060 if (d != null) { 1061 d.method() 1062 } 1063 } 1064 1065.. index:: 1066 type 1067 entity 1068 local variable 1069 interface type 1070 class type 1071 union type 1072 context 1073 compiler 1074 narrowing 1075 smart cast 1076 smart type 1077 if statement 1078 conditional expression 1079 entity 1080 class type 1081 static type 1082 narrowed type 1083 instanceof 1084 null 1085 semantic check 1086 reference equality 1087 1088In like cases, a smart compiler can deduce the smart type of an entity without 1089requiring unnecessary casting conversions (see :ref:`Cast Expression`). 1090 1091Overloading (see :ref:`Function, Method and Constructor Overloading`) can cause 1092tricky situations when a smart type leads to the call of a function or a method 1093(see :ref:`Overload Resolution`) that suits smart rather than static type of an 1094argument: 1095 1096.. code-block:: typescript 1097 :linenos: 1098 1099 function foo (p: Base) {} 1100 function foo (p: Derived) {} 1101 1102 function too() { 1103 let b: Base = new Derived 1104 foo (b) // potential ambiguity in case of smart type, foo(p:Base) is to be called 1105 foo (b as Derived) // no ambiguity, foo(p:Derived) is to be called 1106 } 1107 1108Particular cases supported by the compiler are determined by the compiler 1109implementation. 1110 1111.. index:: 1112 compiler 1113 smart type 1114 smart compiler 1115 entity 1116 casting conversion 1117 overloading 1118 conversion 1119 function 1120 method 1121 conversion overloading 1122 function overloading 1123 method overloading 1124 static type 1125 argument 1126 implementation 1127 compiler 1128 1129| 1130 1131.. _Overloading and Overriding: 1132 1133Overloading and Overriding 1134************************** 1135 1136Two important concepts apply to different contexts and entities throughout 1137this specification as follows: 1138 1139#. *Overloading* allows defining and using functions (in general sense, 1140 including methods and constructors) with the same name but different 1141 signatures. The actual function to be called is determined at compile 1142 time. Thus, *overloading* is related to compile-time polymorphism. 1143 1144#. *Overriding* is closely connected with inheritance. It is used on methods 1145 but not on functions. Overriding allows a subclass to offer a specific 1146 implementation of a method already defined in its parent class. 1147 The actual method to be called is determined at runtime based on object type. 1148 Thus, overriding is related to runtime polymorphism. 1149 1150|LANG| uses two semantic rules related to these concepts: 1151 1152- *Overload-equivalence* rule: the *overloading* of two entities is 1153 correct if their signatures are **not** *overload-equivalent* (see 1154 :ref:`Overload-Equivalent Signatures`). 1155 1156- *Override-compatibility* rule: the *overriding* of two entities is 1157 correct if their signatures are *override-compatible* (see 1158 :ref:`Override-Compatible Signatures`). 1159 1160See :ref:`Overloading for Functions`, 1161:ref:`Overloading and Overriding in Classes`, and 1162:ref:`Overloading and Overriding in Interfaces` for details. 1163 1164.. index:: 1165 overloading 1166 overriding 1167 context 1168 entity 1169 function 1170 constructor 1171 method 1172 signature 1173 compile-time polymorphism 1174 subclass 1175 runtime polymorphism 1176 inheritance 1177 parent class 1178 object type 1179 runtime 1180 overload-equivalence 1181 override-compatibility 1182 overload-equivalent signature 1183 overriding 1184 overloading 1185 1186| 1187 1188.. _Overload-Equivalent Signatures: 1189 1190Overload-Equivalent Signatures 1191============================== 1192 1193.. meta: 1194 frontend_status: Partly 1195 1196Signatures *S1* with parameters *S1P*:sub:`1`, ... , *S1P*:sub:`n`, and *S2* with 1197the same number of parameters *S2P*:sub:`1`, ... , *S2P*:sub:`n` 1198are *overload-equivalent* if the *effective types* of parameters (see 1199:ref:`Type Erasure`) *S1P*:sub:`i` and *S2P*:sub:`i` for each *i* are 1200*overload-equavalent*. 1201 1202**Notes:** 1203 1204- For an optional parameter (see :ref:`Optional Parameters`) in the form 1205 ``ident?: T``, the actual parameter type is considered, i.e., union type 1206 ``T | undefined``. 1207 1208- Type parameter constraint ``Object|null|undefined`` (see 1209 :ref:`Type Parameter Constraint`) is condidered for a type parameter if 1210 no constraint is set explicitly. 1211 1212Parameters *S1P*:sub:`i` and *S2P*:sub:`i` are *overload-equavalent*, if 1213the are simultaneously ``rest`` or not ``rest`` parameters and if: 1214 1215#. Type of *S1P*:sub:`i` is a *type parameter* and type of *S2P*:sub:`i` 1216 is a subtype of *type parameter constraint* or a *type parameter*; 1217 1218#. Type of *S1P*:sub:`i` is *generic type* 1219 ``G`` <``T``:sub:`1`, ``...``, ``T``:sub:`n`>, where at least one 1220 ``T``:sub:`i` is a type parameter, and a 1221 type of *S2P*:sub:`i` is also ``G`` with any 1222 list of :ref:`Type Arguments` or a *union type* that contains ``G``; 1223 1224#. Types of *S1P*:sub:`i` and *S2P*:sub:`i` are 1225 *union types* containing types that fall into either provision above; 1226 1227#. Types of *S1P*:sub:`i` and *S2P*:sub:`i` are identical (see 1228 :ref:`Type Identity`). 1229 1230Parameter names and return types do not influence *overload equivalence*. 1231Signatures are *overload-equivalent* in the following examples: 1232 1233.. index:: 1234 overload-equivalent signature 1235 signature 1236 parameter 1237 type parameter 1238 parameter type 1239 non-generic reference type 1240 union type 1241 reference type 1242 generic type 1243 type argument 1244 overriding 1245 parameter name 1246 return type 1247 overload equivalence 1248 type identity 1249 overload equivalence 1250 1251.. code-block-meta: 1252 1253.. code-block:: typescript 1254 :linenos: 1255 1256 (x: number): void 1257 (y: number): void 1258 1259.. code-block-meta: 1260 1261.. code-block:: typescript 1262 :linenos: 1263 1264 (x: number): void 1265 (y: number): number 1266 1267.. code-block-meta: 1268 1269.. code-block:: typescript 1270 :linenos: 1271 1272 class G<T> 1273 (y: number): void 1274 (x: T): void 1275 1276.. code-block-meta: 1277 1278.. code-block:: typescript 1279 :linenos: 1280 1281 class G<T> 1282 (y: G<number>): void 1283 (x: G<T>): void 1284 1285 1286.. code-block-meta: 1287 1288.. code-block:: typescript 1289 :linenos: 1290 1291 class G<T, S> 1292 (y: T): void 1293 (x: S): void 1294 1295 1296Signatures are not *overload-equivalent* in the following examples: 1297 1298.. index:: 1299 overload-equivalent signature 1300 1301.. code-block-meta: 1302 1303.. code-block:: typescript 1304 :linenos: 1305 1306 (x: number): void 1307 (y: string): void 1308 1309.. code-block-meta: 1310 1311.. code-block:: typescript 1312 :linenos: 1313 1314 class A { /*body*/} 1315 class B extends A { /*body*/} 1316 (x: A): void 1317 (y: B): void 1318 1319.. code-block-meta: 1320 1321.. code-block:: typescript 1322 :linenos: 1323 1324 class A<T> { 1325 (p: T) 1326 (p: T[]) 1327 1328.. code-block-meta: 1329 1330.. code-block:: typescript 1331 :linenos: 1332 1333 class Base {} 1334 class Derived1 extends Base {} 1335 class Derived2 extends Base {} 1336 (p: Derived1 | Derived2 ): void 1337 (p: Base): void 1338 1339.. code-block-meta: 1340 1341.. code-block:: typescript 1342 :linenos: 1343 1344 class G<T> 1345 (x: G<number>): void 1346 (y: G<string>): void 1347 1348.. code-block-meta: 1349 1350.. code-block:: typescript 1351 :linenos: 1352 1353 class G<T extends number> 1354 (x: T): void 1355 (y: string): void 1356 1357| 1358 1359.. _Override-Compatible Signatures: 1360 1361Override-Compatible Signatures 1362============================== 1363 1364.. meta: 1365 frontend_status: Partly 1366 1367If there are two classes ``Base`` and ``Derived``, and class ``Derived`` 1368overrides the method ``foo()`` of ``Base``, then ``foo()`` in ``Base`` has 1369signature ``S``:sub:`1` <``V``:sub:`1` ``, ... V``:sub:`k`> 1370(``U``:sub:`1` ``, ..., U``:sub:`n`) ``:U``:sub:`n+1`, and ``foo()`` in 1371``Derived`` has signature ``S``:sub:`2` <``W``:sub:`1` ``, ... W``:sub:`l`> 1372(``T``:sub:`1` ``, ..., T``:sub:`m`) ``:T``:sub:`m+1` as in the example below: 1373 1374.. index:: 1375 override-compatible signature 1376 class 1377 base class 1378 derived class 1379 signature 1380 1381.. code-block:: typescript 1382 :linenos: 1383 1384 class Base { 1385 foo <V1, ... Vk> (p1: U1, ... pn: Un): Un+1 1386 } 1387 class Derived extends Base { 1388 override foo <W1, ... Wl> (p1: T1, ... pm: Tm): Tm+1 1389 } 1390 1391The signature ``S``:sub:`2` is override-compatible with ``S``:sub:`1` only 1392if **all** of the following conditions are met: 1393 13941. Number of parameters of both methods is the same, i.e., ``n = m``. 13952. Each parameter type ``T``:sub:`i` is a supertype of ``U``:sub:`i` 1396 for ``i`` in ``1..n`` (contravariance). 13973. If return type ``T``:sub:`m+1` is ``this``, then ``U``:sub:`n+1` is ``this``, 1398 or any of superinterfaces or superclass of the current type. Otherwise, 1399 return type ``T``:sub:`m+1` is a subtype of ``U``:sub:`n+1` (covariance). 14004. Number of type parameters of either method is the same, i.e., ``k = l``. 14015. Constraints of ``W``:sub:`1`, ... ``W``:sub:`l` are to be contravariant 1402 (see :ref:`Invariance, Covariance and Contravariance`) to the appropriate 1403 constraints of ``V``:sub:`1`, ... ``V``:sub:`k`. 1404 1405.. index:: 1406 signature 1407 override-compatible signature 1408 override compatibility 1409 class 1410 signature 1411 method 1412 parameter 1413 type 1414 contravariant 1415 covariance 1416 invariance 1417 constraint 1418 type parameter 1419 1420The following rule applies to generics: 1421 1422 - Derived class must have type parameter constraints to be subtype 1423 (see :ref:`Subtyping`) of the respective type parameter 1424 constraint in the base type; 1425 - Otherwise, a :index:`compile-time error` occurs. 1426 1427.. index:: 1428 generic 1429 derived class 1430 subtyping 1431 subtype 1432 type parameter 1433 base type 1434 1435.. code-block:: typescript 1436 :linenos: 1437 1438 class Base {} 1439 class Derived extends Base {} 1440 class A1 <CovariantTypeParameter extends Base> {} 1441 class B1 <CovariantTypeParameter extends Derived> extends A1<CovariantTypeParameter> {} 1442 // OK, derived class may have type compatible constraint of type parameters 1443 1444 class A2 <ContravariantTypeParameter extends Derived> {} 1445 class B2 <ContravariantTypeParameter extends Base> extends A2<ContravariantTypeParameter> {} 1446 // Compile-time error, derived class cannot have non-compatible constraints of type parameters 1447 1448The semantics is illustrated by the examples below: 1449 14501. **Class/Interface Types** 1451 1452.. code-block:: typescript 1453 :linenos: 1454 1455 interface Base { 1456 param(p: Derived): void 1457 ret(): Base 1458 } 1459 1460 interface Derived extends Base { 1461 param(p: Base): void // Contravariant parameter 1462 ret(): Derived // Covariant return type 1463 } 1464 1465.. index:: 1466 class type 1467 interface type 1468 contravariant parameter 1469 covariant return type 1470 14712. **Function Types** 1472 1473.. code-block:: typescript 1474 :linenos: 1475 1476 interface Base { 1477 param(p: (q: Base)=>Derived): void 1478 ret(): (q: Derived)=> Base 1479 } 1480 1481 interface Derived extends Base { 1482 param(p: (q: Derived)=>Base): void // Covariant parameter type, contravariant return type 1483 ret(): (q: Base)=> Derived // Contravariant parameter type, covariant return type 1484 } 1485 1486.. index:: 1487 function type 1488 covariant parameter type 1489 contravariant return type 1490 contravariant parameter type 1491 covariant return type 1492 14933. **Union Types** 1494 1495.. code-block:: typescript 1496 :linenos: 1497 1498 interface BaseSuperType {} 1499 interface Base extends BaseSuperType { 1500 // Overriding for parameters 1501 param<T extends Derived, U extends Base>(p: T | U): void 1502 1503 // Overriding for return type 1504 ret<T extends Derived, U extends Base>(): T | U 1505 } 1506 1507 interface Derived extends Base { 1508 // Overriding kinds for parameters, Derived <: Base 1509 param<T extends Base, U extends Object>( 1510 p: Base | BaseSuperType // contravariant parameter type: Derived | Base <: Base | BaseSuperType 1511 ): void 1512 // Overriding kinds for return type 1513 ret<T extends Base, U extends BaseSuperType>(): T | U 1514 } 1515 1516.. index:: 1517 union type 1518 return type 1519 15204. **Type Parameter Constraint** 1521 1522.. code-block:: typescript 1523 :linenos: 1524 1525 interface Base { 1526 param<T extends Derived>(p: T): void 1527 ret<T extends Derived>(): T 1528 } 1529 1530 interface Derived extends Base { 1531 param<T extends Base>(p: T): void // Contravariance for constraints of type parameters 1532 ret<T extends Base>(): T // Contravariance for constraints of the return type 1533 } 1534 1535 1536The example below illustrates override compatibility with ``Object``: 1537 1538.. index:: 1539 contravariance 1540 constraint 1541 return type 1542 type parameter 1543 override compatibility 1544 1545.. code-block:: typescript 1546 :linenos: 1547 1548 interface Base { 1549 kinds_of_parameters<T extends Derived, U extends Base>( // It represents all possible kinds of parameter type 1550 p01: Derived, 1551 p02: (q: Base)=>Derived, 1552 p03: number, 1553 p04: Number, 1554 p05: T | U, 1555 p06: E1, 1556 p07: Base[], 1557 p08: [Base, Base] 1558 ): void 1559 kinds_of_return_type(): Object // It can be overridden by all subtypes except primitive ones 1560 } 1561 interface Derived extends Base { 1562 kinds_of_parameters( // Object is a supertype for all types except primitive ones 1563 p1: Object, 1564 p2: Object, 1565 p3: Object, // Compile-time error: number and Object are not override-compatible 1566 p4: Object, 1567 p5: Object, 1568 p6: Object, 1569 p7: Object, 1570 p8: Object 1571 ): void 1572 } 1573 1574 interface Derived1 extends Base { 1575 kinds_of_return_type(): Base // Valid overriding 1576 } 1577 interface Derived2 extends Base { 1578 kinds_of_return_type(): (q: Derived)=> Base // Valid overriding 1579 } 1580 interface Derived3 extends Base { 1581 kinds_of_return_type(): number // Valid overriding 1582 } 1583 interface Derived4 extends Base { 1584 kinds_of_return_type(): number | string // Valid overriding 1585 } 1586 interface Derived5 extends Base { 1587 kinds_of_return_type(): E1 // Valid overriding 1588 } 1589 interface Derived6 extends Base { 1590 kinds_of_return_type(): Base[] // Valid overriding 1591 } 1592 interface Derived7 extends Base { 1593 kinds_of_return_type(): [Base, Base] // Valid overriding 1594 } 1595 1596.. index:: 1597 parameter type 1598 overriding 1599 subtype 1600 supertype 1601 overriding 1602 compatibility 1603 1604| 1605 1606.. _Overloading for Functions: 1607 1608Overloading for Functions 1609========================= 1610 1611.. meta: 1612 frontend_status: Partly 1613 1614*Overloading* must only be considered for functions because inheritance for 1615functions is not defined. 1616 1617The correctness check for functions overloading is performed if two or more 1618functions with the same name are accessible (see :ref:`Accessible`) in a scope 1619(see :ref:`Scopes`). 1620 1621A function can be declared in, or imported to a scope. 1622 1623The semantic check for overloading functions is as follows: 1624 1625- If function signatures are *overload-equivalent*, then 1626 a :index:`compile-time error` occurs. 1627 1628- Otherwise, *overloading* is valid. 1629 1630It is discussed in detail in :ref:`Function Overloading` and 1631:ref:`Import and Overloading of Function Names`. 1632 1633.. index:: 1634 overloading 1635 function 1636 inheritance 1637 correctness check 1638 semantic check 1639 accessibility 1640 access 1641 scope 1642 import 1643 compilation unit 1644 overload-equivalent signature 1645 1646| 1647 1648.. _Overloading and Overriding in Classes: 1649 1650Overloading and Overriding in Classes 1651===================================== 1652 1653.. meta: 1654 frontend_status: Partly 1655 1656Both *overloading* and *overriding* must be considered in case of classes for 1657methods and partly for constructors. 1658 1659**Note**. Only accessible (see :ref:`Accessible`) methods are subjected to 1660overloading and overriding. The same rules also apply to accessors in case of 1661overriding. 1662 1663An overriding member can keep or extend an access modifier (see 1664:ref:`Access Modifiers`) of a member that is inherited or implemented. 1665Otherwise, a :index:`compile-time error` occurs. 1666 1667An attempt to override a private method of a superclass, or to declare a method 1668with the same name as the private method with default implementation from any 1669superinterface causes a :index:`compile-time error`. 1670 1671.. index:: 1672 overloading 1673 inheritance 1674 overriding 1675 class 1676 constructor 1677 accessibility 1678 access 1679 private method 1680 method 1681 subclass 1682 accessor 1683 superclass 1684 access modifier 1685 implementation 1686 superinterface 1687 1688.. code-block:: typescript 1689 :linenos: 1690 1691 class Base { 1692 public public_member() {} 1693 protected protected_member() {} 1694 internal internal_member() {} 1695 private private_member() {} 1696 } 1697 1698 interface Interface { 1699 public_member() // All members are public in interfaces 1700 private private_member() {} // Except private methods with default implementation 1701 } 1702 1703 class Derived extends Base implements Interface { 1704 public override public_member() {} 1705 // Public member can be overridden and/or implemented by the public one 1706 public override protected_member() {} 1707 // Protected member can be overridden by the protected or public one 1708 internal internal_member() {} 1709 // Internal member can be overridden by the internal one only 1710 override private_member() {} 1711 // A compile-time error occurs if an attempt is made to override private member 1712 // or implement the private methods with default implementation 1713 } 1714 1715The table below represents semantic rules that apply in various contexts: 1716 1717.. list-table:: 1718 :width: 100% 1719 :widths: 50 50 1720 :header-rows: 1 1721 1722 * - Context 1723 - Semantic Check 1724 * - Two *instance methods*, two *static methods* with the same name, or two 1725 *constructors* are defined in the same class. 1726 - If signatures are *overload-equivalent*, (see :ref:`Overload-Equivalent 1727 Signatures`), then a :index:`compile-time error` occurs. Otherwise, 1728 *overloading* is used. 1729 1730 1731.. index:: 1732 semantic check 1733 instance method 1734 method 1735 static method 1736 constructor 1737 overload equivalence 1738 overloading 1739 overload-equivalent signature 1740 overriding 1741 implementation 1742 public 1743 internal 1744 private 1745 1746.. code-block:: typescript 1747 :linenos: 1748 1749 class aClass { 1750 1751 instance_method_1() {} 1752 instance_method_1() {} // compile-time error: instance method duplication 1753 1754 static static_method_1() {} 1755 static static_method_1() {} // compile-time error: static method duplication 1756 1757 instance_method_2() {} 1758 instance_method_2(p: number) {} // valid overloading 1759 1760 static static_method_2() {} 1761 static static_method_2(p: string) {} // valid overloading 1762 1763 constructor() {} 1764 constructor() {} // compile-time error: constructor duplication 1765 1766 constructor(p: number) {} 1767 constructor(p: string) {} // valid overloading 1768 1769 } 1770 1771.. list-table:: 1772 :width: 100% 1773 :widths: 50 50 1774 :header-rows: 0 1775 1776 * - An *instance method* is defined in a subclass with the same name as the 1777 *instance method* in a superclass. 1778 - If signatures are *override-compatible* (see 1779 :ref:`Override-Compatible Signatures`), then *overriding* is used. 1780 Otherwise, *overloading* is used. 1781 1782 1783.. code-block:: typescript 1784 :linenos: 1785 1786 class Base { 1787 method_1() {} 1788 method_2(p: number) {} 1789 } 1790 class Derived extends Base { 1791 override method_1() {} // overriding 1792 method_2(p: string) {} // overloading 1793 } 1794 1795.. list-table:: 1796 :width: 100% 1797 :widths: 50 50 1798 :header-rows: 0 1799 1800 * - A *static method* is defined in a subclass with the same name as the 1801 *static method* in a superclass. 1802 - If signatures are *overload-equivalent* (see 1803 :ref:`Overload-Equivalent Signatures`), then the static method in the 1804 subclass *hides* the previous static method.Otherwise, *overloading* is 1805 used. 1806 1807.. index:: 1808 instance method 1809 static method 1810 subclass 1811 superclass 1812 override-compatible signature 1813 override-compatibility 1814 overloading 1815 hiding 1816 overriding 1817 1818.. code-block:: typescript 1819 :linenos: 1820 1821 class Base { 1822 static method_1() {} 1823 static method_2(p: number) {} 1824 } 1825 class Derived extends Base { 1826 static method_1() {} // hiding 1827 static method_2(p: string) {} // overloading 1828 } 1829 1830.. list-table:: 1831 :width: 100% 1832 :widths: 50 50 1833 :header-rows: 0 1834 1835 * - A *constructor* is defined in a subclass. 1836 - All base class constructors are available for call in all derived class 1837 constructors. 1838 1839 1840.. code-block:: typescript 1841 :linenos: 1842 1843 class Base { 1844 constructor() {} 1845 constructor(p: number) {} 1846 } 1847 class Derived extends Base { 1848 constructor(p: string) { 1849 super() 1850 super(5) 1851 } 1852 } 1853 1854.. index:: 1855 constructor 1856 subclass 1857 class constructor 1858 derived class constructor 1859 1860| 1861 1862.. _Overloading and Overriding in Interfaces: 1863 1864Overloading and Overriding in Interfaces 1865======================================== 1866 1867.. meta: 1868 frontend_status: Done 1869 1870.. list-table:: 1871 :width: 100% 1872 :widths: 50 50 1873 :header-rows: 1 1874 1875 * - Context 1876 - Semantic Check 1877 * - A method is defined in a subinterface with the same name as the method 1878 in the superinterface. 1879 - If signatures are *override-compatible* (see 1880 :ref:`Override-Compatible Signatures`), then *overriding* is used. 1881 Otherwise, *overloading* is used. 1882 1883.. code-block:: typescript 1884 :linenos: 1885 1886 interface Base { 1887 method_1() 1888 method_2(p: number) 1889 } 1890 interface Derived extends Base { 1891 method_1() // overriding 1892 method_2(p: string) // overloading 1893 } 1894 1895 1896.. list-table:: 1897 :width: 100% 1898 :widths: 50 50 1899 :header-rows: 0 1900 1901 * - Two methods with the same name are defined in the same interface. 1902 - *Overloading* is used. A :index:`compile-time error` occurs if signatures 1903 are *overload-equivalent*. 1904 1905 1906.. index:: 1907 method 1908 subinterface 1909 superinterface 1910 semantic check 1911 override-compatible 1912 overload-equivalent 1913 interface 1914 overloading 1915 1916.. code-block:: typescript 1917 :linenos: 1918 1919 interface anInterface { 1920 instance_method_1() 1921 instance_method_1() // Compile-time error: instance method duplication 1922 1923 instance_method_2() 1924 instance_method_2(p: number) // Valid overloading 1925 } 1926 1927| 1928 1929.. _Overload Resolution: 1930 1931Overload Resolution 1932******************* 1933 1934.. meta: 1935 frontend_status: Done 1936 1937*Overload resolution* is used to select one entity to call from a set of 1938*potentially applicable candidates* in a function, method, or constructor call. 1939Overload resolution is performed in two steps as follows: 1940 1941#. Select *applicable candidates* from *potentially applicable candidates*; 1942 1943#. If there is more than one *applicable candidate*, then select the *best 1944 candidate*. 1945 1946**Note**. The first step is performed in all cases, even if there is 1947only one *applicable candidate* to check *call signature compatibility*. 1948 1949.. index:: 1950 overload resolution 1951 entity 1952 applicable candidate 1953 call signature compatibility 1954 constructor call 1955 constructor 1956 potentially applicable candidate 1957 best candidate 1958 1959| 1960 1961.. _Selection of Applicable Candidates: 1962 1963Selection of Applicable Candidates 1964================================== 1965 1966.. meta: 1967 frontend_status: Partly 1968 todo: adapt the implementation to the latest specification (handle rest, union, functional types properly) 1969 todo: make the ISA/assembler/runtime handle union types without collision - eg foo(arg: A|B) and foo(arg: C|D) 1970 1971The selection of *applicable candidates* is the process of checking 1972:ref:`Compatibility of Call Arguments` for all entities from the set of 1973*potentially applicable candidates*. If any argument is not compatible with 1974the corresponding parameter type, then the entity is deleted from the set. 1975 1976**Note**. Compile-time errors are not reported at this stage. 1977 1978After processing all entities, one of the following results is achieved: 1979 1980- Set is empty (all entities are deleted). A compile-time error occurs, 1981 and the *overload resolution* is completed. 1982 1983- Only one entity is left in the set. This is the entity to call, and 1984 the *overload resolution* is completed. 1985 1986- More than one entity is left in the set. The next step of the 1987 *overload resolution* is to be performed. 1988 1989.. index:: 1990 applicable candidate 1991 potentially applicable candidate 1992 semantic check 1993 compatibility 1994 call argument 1995 entity 1996 parameter type 1997 overload resolution 1998 overloaded function 1999 call 2000 2001Two overloaded functions are considered in the following example: 2002 2003.. code-block:: typescript 2004 :linenos: 2005 2006 class Base { } 2007 class Derived extends Base { } 2008 2009 function foo(p: Base) { ... } // #1 2010 function foo(p: Derived) { ... } // #2 2011 2012 foo(new Derived) // two applicable candidates for this call 2013 // next step of overload resolution is required 2014 2015 foo(new Base) // one applicable candidate 2016 // overload resolution is completed 2017 // #1 will be called 2018 2019 foo(new Base, 5) // no candidates, compile-time error 2020 2021| 2022 2023.. _Selection of Best Candidate: 2024 2025Selection of Best Candidate 2026=========================== 2027 2028.. meta: 2029 frontend_status: Partly 2030 2031If the set of *applicable candidates* has two or more candidates, then the 2032best candidate for the given list of arguments is to be identified, if possible. 2033 2034The selection of the best candidate is based on the following: 2035 2036- There are no candidates with the same list of parameters, as this situation 2037 is already forbidden by the compiler (at the place of declaration or import) 2038 (see :ref:`Overload-Equivalent Signatures`); 2039 2040- If several candidates can be called correctly by using the same argument list, 2041 then at least one implicit argument transformation must be applied to make 2042 the call. 2043 2044Possible argument transformations are listed below: 2045 2046- Passing default values to fill any missing arguments 2047 (:ref:`Optional Parameters`); 2048 2049- Passing the empty array to replace a ``rest`` parameter that has no argument; 2050 2051- Folding several arguments to the array for a ``rest`` parameter. 2052 2053.. index:: 2054 applicable candidate 2055 best candidate 2056 parameter 2057 compiler 2058 import site 2059 argument transformation 2060 value 2061 overload-equivalent signature 2062 rest parameter 2063 conversion 2064 array 2065 rest parameter 2066 2067The examples of transformations are presented below: 2068 2069.. code-block:: typescript 2070 :linenos: 2071 2072 function foo1(x?: string) {} 2073 foo1() // passing default value -> foo(undefined) 2074 2075 function foo2(...x: int[]) {} 2076 foo2() // passing empty array -> foo([]) 2077 foo2(1, 2) // folding to array -> foo(...[1, 2]) 2078 2079The *best candidate* is the candidate that requires no transformation for all 2080arguments. If there is such a single candidate, then other candidates are not 2081considered. Such *best candidate* is represented 2082in the example below: 2083 2084.. code-block:: typescript 2085 :linenos: 2086 2087 function max(a: number, b: number) // #1 2088 function max(...args: number[]) // #2 2089 2090 max(1, 2) // #1 - is the best candidate, no transformation 2091 2092.. index:: 2093 best candidate 2094 transformation 2095 argument 2096 2097If there is no *best candidate* at this step, then each candidate 2098is compared to other candidates. 2099The following sequence of checks is used to calculate a partially *better* 2100relation based on the comparison of candidates *C1* and *C2*: 2101 2102 2103**Check 1**. If *C1* has fewer parameters, i.e., default values or an empty 2104``rest`` argument are used instead of the absent arguments in the *C2* call, 2105then *C1* is *better*. 2106 2107.. code-block:: typescript 2108 :linenos: 2109 2110 function foo(n: number, s?: string) // #1 2111 function foo(n: number) // #2 2112 2113 foo(1) // #2 is better, less parameters 2114 2115 function bar(...args: number[]) // #1 2116 function bar() // #2 2117 2118 bar() // #2 is better, less parameters 2119 2120 function goo(...args: number[]) // #1 2121 function goo(n?: number) // #2 2122 2123 goo() // none is better 2124 2125.. index:: 2126 best candidate 2127 better candidate 2128 partially better candidate 2129 rest argument 2130 2131**Check 2**. If *C1* has a non-``rest`` parameter(s) for a non-empty list of 2132arguments, and *C2* has a ``rest`` parameter, then *C1* is *better*. 2133 2134.. code-block:: typescript 2135 :linenos: 2136 2137 function foo(sum: number, a: number, b: number) // #1 2138 function foo(sum: number, ...x: number[]) // #2 2139 2140 foo(1, 2, 3) // #1 is better, non-rest parameters 2141 2142.. index:: 2143 argument 2144 better candidate 2145 rest argument 2146 2147**Check 3**. If an argument type is a subtype of parameter type for *C1* and 2148not for *C2*, then *C1* is *better* for this argument. 2149 2150.. code-block:: typescript 2151 :linenos: 2152 2153 function foo(n: int) // #1 2154 function foo(n: long) // #2 2155 2156 foo(1) // #1 is better, argument type is subtype of parameter type 2157 foo(1 as long) // #2 is better 2158 2159.. index:: 2160 argument 2161 better candidate 2162 argument transformation 2163 2164**Check 4**. If an argument type is a subtype of parameter type for both *C1* 2165and *C2*, but type of *C1* is identical for the argument type and type of *C2* 2166is not, then *C1* is *better* for this argument. 2167 2168.. code-block:: typescript 2169 :linenos: 2170 2171 class C {} 2172 class D extends C {} 2173 2174 function foo(x: C) {} // #1 2175 function foo(x: D) {} // #2 2176 2177 foo(new C) // #1 is better 2178 2179**Check 5**. Otherwise, none is better for this argument, including cases: 2180 2181- An argument type is a subtype of parameter type for both *C1* 2182 and *C2*, but neither is identical; 2183 2184- An argument type is not a subtype for both *C1* and *C2*. 2185 2186.. code-block:: typescript 2187 :linenos: 2188 2189 function foo(x: number | boolean) // #1 2190 function foo(x: number | string) // #2 2191 2192 foo(1.) // both subtype, none identical: none is better 2193 2194 function negate(x: long) // #1 2195 function negate(x: double) // #2 2196 2197 negate(1) // none subtype: none is better 2198 2199.. index:: 2200 best candidate 2201 better candidate 2202 argument transformation 2203 numeric type 2204 conversion 2205 parameter 2206 2207A :index:`compile-time error` occurs if 2208*C1* is *better* for one argument, and *C2* is *better* for another argument 2209as represented in the example below: 2210 2211.. code-block:: typescript 2212 :linenos: 2213 2214 function goo(a: int; b: int | string) // #1 2215 function goo(a: int | string, b: int) // #2 2216 2217 goo(1, 1) // compile-time error, as 2218 // #1 is better for 1st argument, 2219 // #2 is better for 2nd argument. 2220 2221.. index:: 2222 best candidate 2223 argument 2224 better candidate 2225 2226 2227If exactly one candidate is *better* than others, 2228then it is the *best candidate*. 2229Otherwise, if no single candidate is *better*, 2230:index:`compile-time error` occurs. 2231 2232| 2233 2234.. _Type Erasure: 2235 2236Type Erasure 2237************* 2238 2239*Type erasure* is the concept that denotes a special handling of some language 2240*types*, primarily :ref:`Generics`, in the semantics of the following language 2241operations that require the type to be preserved for execution: 2242 2243- :ref:`InstanceOf Expression`; 2244- :ref:`Cast Expression`; 2245- :ref:`Overload-Equivalent Signatures`. 2246 2247In these operations some *types* are handled as their corresponding *effective 2248types*, while the *effective type* is defined as type mapping. The *effective 2249type* of a specific type ``T`` is always a supertype of ``T``. As a result, 2250two kinds of relationship are possible between an original type and an 2251*effective type*: 2252 2253- *Effective type* of ``T`` is identical to ``T``, and *type erasure* has no 2254 effect. 2255 2256- If *effective type* of ``T`` is not identical to ``T``, then the type ``T`` 2257 is considered affected by *type erasure*, i.e., *erased*. 2258 2259.. index:: 2260 type erasure 2261 instanceof expression 2262 cast expression 2263 overload-equivalent signature 2264 operation 2265 type 2266 effective type 2267 type mapping 2268 supertype 2269 2270In addition, accessing a value of type ``T``, including by 2271:ref:`Field Access Expression`, :ref:`Method Call Expression`, or 2272:ref:`Function Call Expression` can cause ``ClassCastError`` thrown if 2273type ``T``and the ``target`` type are both affected by *type erasure*, and the 2274value is produced by :ref:`Cast Expression`. 2275 2276.. code-block:: typescript 2277 :linenos: 2278 2279 class A<T> { 2280 field?: T 2281 2282 test(value: Object) { 2283 return value instanceof T // CTE, T is erased 2284 } 2285 2286 cast(value: Object) { 2287 return value as T // OK, but check is postponed 2288 } 2289 } 2290 2291 function castToA(p: Object) { 2292 p instanceof A<number> // CTE, A<number> is erased 2293 2294 return p as A<number> // OK, but check is performed against A 2295 } 2296 2297.. index:: 2298 type erasure 2299 field access 2300 method call 2301 target type 2302 cast expression 2303 2304Type mapping determines the *effective types* as follows: 2305 2306- :ref:`Type Parameter Constraint` for :ref:`Type Parameters`. 2307 2308- Instantiation of the same generic type (see 2309 :ref:`Explicit Generic Instantiations`) for *generic types* (see 2310 :ref:`Generics`), with its type arguments selected in accordance with 2311 :ref:`Type Parameter Variance` as outlined below: 2312 2313 - *Covariant* type parameters are instantiated with the constraint type; 2314 2315 - *Contravariant* type parameters are instantiated with the type ``never``; 2316 2317 - *Invariant* type parameters have no corresponding type argument, **TBD** 2318 2319- Union type constructed from the effective types of types ``T1 | T2 ... Tn`` 2320 within the original union type for :ref:`Union Types` in the form 2321 ``T1 | T2 ... Tn``. 2322 2323- Same for :ref:`Array Types` in the form ``T[]`` as for generic type ``Array<T>``. 2324 2325- Instantiation of ``FixedArray`` for ``FixedArray<T>`` instantiations, with 2326 the effective type of type argument ``T`` preserved. 2327 2328- Instantiation of an internal generic function type with respect to 2329 the number of parameter types *n* for :ref:`Function Types` in the form 2330 ``(P1, P2 ..., Pn) => R``. Parameter types ``P1, P2 ... Pn`` are 2331 instantiated with ``object | null | undefined``, and the return type ``R`` 2332 is instantiated with type ``never``. 2333 2334- Instantiation of an internal generic tuple type with respect to 2335 the number of element types *n* for :ref:`Tuple Types` in the form 2336 ``[T1, T2 ..., Tn]``. **TBD** 2337 2338- String for *string literal types* (see :ref:`Literal Types`). 2339 2340- Enumeration base type of the same const enum type for *const enum* types 2341 (see :ref:`Enumerations`). 2342 2343- Otherwise, the original type is preserved. 2344 2345.. index:: 2346 type erasure 2347 type mapping 2348 generic type 2349 effective type 2350 instantiation 2351 type argument 2352 covariant type parameter 2353 type parameter 2354 contravariant type parameter 2355 invariant type parameter 2356 parameter type 2357 type argument 2358 type preservation 2359 2360| 2361 2362.. _Static Initialization: 2363 2364Static Initialization 2365********************* 2366 2367*Static initialization* is a routine performed once for each class 2368(see :ref:`Classes`), namespace (see :ref:`Namespace Declarations`), 2369separate module (see :ref:`Separate Modules`) or package module (see :ref:`Packages`). 2370 2371*Static initialization* execution involves execution of: 2372 2373- *Initializers* of *variables* or *static fields* 2374 2375- *Top-level statements* 2376 2377- Code inside *Static block* 2378 2379 2380*Static initialization* is performed before one of the following operations is first excecuted: 2381 2382- a static method or function of entity's scope is invoked 2383 2384- a static field or variable of entity's scope is accessed 2385 2386- entity, which is an interface or class, is instantiated 2387 2388- entity is a class, and its direct subclass is *statically initialized* 2389 2390Note: Any of the enlisted operations does not invoke *static initialization* 2391recursively if the *static initializaton* of the same entity is not complete. 2392 2393If *static initialization* routine execution is terminated due to the 2394exception thrown, then the initialization is not complete, 2395and any attempt to execute its *static initialization* once again will 2396produce an exception. 2397 2398For the concurrent execution (see :ref:`Coroutines (Experimental)`) 2399*static initialization* routine invokation involves synchronization 2400between all *coroutines* that try to invoke it to ensure that 2401initialization is performed only once and the operations 2402that require *static initialization* to be performed are executed after 2403the initialization completes. 2404 2405If *static initialization* routines of two concurrently initialized classes 2406has a circular dependence, it may lead to deadlock. 2407 2408| 2409 2410.. _Static Initialization Safety: 2411 2412Static Initialization Safety 2413============================ 2414 2415If a *named reference* refers to a not yet initialized *entity*, including 2416 2417- variable (see :ref:`Variable and Constant Declarations`) of a separate module 2418 package (see :ref:`Packages`), or namespace (see :ref:`Namespace Declarations`) 2419 2420- a static field of the class (see :ref:`Static Fields`) 2421 2422then a compile-time error is produced. 2423 2424If it is not possible to detect an access to a not yet initalized *entity*, 2425then the runtime evaluation is performed as follows: 2426 2427- If type of the entity has a default value, then a default value is produced 2428 2429- Otherwise, ``NullPointerError`` is thrown 2430 2431 2432.. _Dispatch: 2433 2434Dispatch 2435******** 2436 2437.. meta: 2438 frontend_status: Done 2439 2440As a result of assignment (see :ref:`Assignment`) to a variable or call (see 2441:ref:`Method Call Expression` or :ref:`Function Call Expression`), the actual 2442runtime type of a parameter of class or interface can become different from the 2443type explicitly specified or inferred at the point of declaration. 2444 2445In this situation method calls are dispatched during program execution based on 2446their actual type. 2447 2448This mechanism is called *dynamic dispatch*. Dynamic dispatch is used in 2449OOP languages to provide greater flexibility and the required level of 2450abstraction. Unlike *static dispatch* where the particular method to be called 2451is known at compile time, *dynamic dispatch* requires additional action during 2452program code execution. Compilation tools can optimize dynamic to static dispatch. 2453 2454.. index:: 2455 dispatch 2456 assignment 2457 variable 2458 call 2459 method call expression 2460 method 2461 method call 2462 function call 2463 function 2464 runtime 2465 runtime type 2466 parameter 2467 class 2468 specified type 2469 inferred type 2470 point of declaration 2471 dynamic dispatch 2472 OOP (object-oriented programming) 2473 static dispatch 2474 compile time 2475 2476| 2477 2478.. _Compatibility Features: 2479 2480Compatibility Features 2481********************** 2482 2483Some features are added to |LANG| in order to support smooth |TS| compatibility. 2484Using these features while doing the |LANG| programming is not recommended in 2485most cases. 2486 2487.. index:: 2488 compatibility 2489 2490| 2491 2492.. _Extended Conditional Expressions: 2493 2494Extended Conditional Expressions 2495================================ 2496 2497.. meta: 2498 frontend_status: Done 2499 2500|LANG| provides extended semantics for conditional expressions 2501to ensure better |TS| alignment. It affects the semantics of the following: 2502 2503- Conditional expressions (see :ref:`Conditional Expressions`, 2504 :ref:`Conditional-And Expression`, :ref:`Conditional-Or Expression`, and 2505 :ref:`Logical Complement`); 2506 2507- ``while`` and ``do`` statements (see :ref:`While Statements and Do Statements`); 2508 2509- ``for`` statements (see :ref:`For Statements`); 2510 2511- ``if`` statements (see :ref:`if Statements`). 2512 2513**Note**. The extended semantics is to be deprecated in one of the future 2514versions of |LANG|. 2515 2516The extended semantics approach is based on the concept of *truthiness* that 2517extends the boolean logic to operands of non-boolean types. 2518 2519Depending on the kind of a valid expression's type, the value of the valid 2520expression can be handled as ``true`` or ``false`` as described in the table 2521below: 2522 2523.. index:: 2524 extended conditional expression 2525 conditional expression 2526 alignment 2527 semantics 2528 conditional-and expression 2529 conditional-or expression 2530 while statement 2531 do statement 2532 for statement 2533 if statement 2534 truthiness 2535 non-boolean type 2536 expression type 2537 2538 2539.. list-table:: 2540 :width: 100% 2541 :widths: 25 25 25 25 2542 :header-rows: 1 2543 2544 * - Value Type Kind 2545 - When ``false`` 2546 - When ``true`` 2547 - |LANG| Code Example to Check 2548 * - ``string`` 2549 - empty string 2550 - non-empty string 2551 - ``s.length == 0`` 2552 * - ``boolean`` 2553 - ``false`` 2554 - ``true`` 2555 - ``x`` 2556 * - ``enum`` 2557 - ``enum`` constant handled as ``false`` 2558 - ``enum`` constant handled as ``true`` 2559 - ``x.valueOf()`` 2560 * - ``number`` (``double``/``float``) 2561 - ``0`` or ``NaN`` 2562 - any other number 2563 - ``n != 0 && !isNaN(n)`` 2564 * - any integer type 2565 - ``== 0`` 2566 - ``!= 0`` 2567 - ``i != 0`` 2568 * - ``bigint`` 2569 - ``== 0n`` 2570 - ``!= 0n`` 2571 - ``i != 0n`` 2572 * - ``null`` or ``undefined`` 2573 - ``always`` 2574 - ``never`` 2575 - ``x != null`` or 2576 2577 ``x != undefined`` 2578 * - Union types 2579 - When value is ``false`` according to this column 2580 - When value is ``true`` according to this column 2581 - ``x != null`` or 2582 2583 ``x != undefined`` for union types with nullish types 2584 * - Any other nonNullish type 2585 - ``never`` 2586 - ``always`` 2587 - ``new SomeType != null`` 2588 2589 2590Extended semantics of :ref:`Conditional-And Expression` and 2591:ref:`Conditional-Or Expression` affects the resultant type of expressions 2592as follows: 2593 2594- A *conditional-and* expression ``A && B`` is of type ``B`` if the result of 2595 ``A`` is handled as ``true``. Otherwise, it is of type ``A``. 2596 2597- A *conditional-or* expression ``A || B`` is of type ``B`` if the result of 2598 ``A`` is handled as ``false``. Otherwise, it is of type ``A``. 2599 2600The example below illustrates the way this approach works in practice. Any 2601``nonzero`` number is handled as ``true``. The loop continues until it becomes 2602``zero`` that is handled as ``false``: 2603 2604.. code-block-meta: 2605 2606.. code-block:: typescript 2607 :linenos: 2608 2609 for (let i = 10; i; i--) { 2610 console.log (i) 2611 } 2612 /* And the output will be 2613 10 2614 9 2615 8 2616 7 2617 6 2618 5 2619 4 2620 3 2621 2 2622 1 2623 */ 2624 2625.. index:: 2626 NaN 2627 nullish expression 2628 numeric expression 2629 conditional-and expression 2630 conditional-or expression 2631 loop 2632 string 2633 integer type 2634 union type 2635 nullish type 2636 nonzero 2637 2638.. raw:: pdf 2639 2640 PageBreak 2641