1# Introduction 2 3Welcome to the tutorial for ArkTS, a TypeScript-based programming language designed specifically to build high-performance mobile applications! 4 5ArkTS is optimized to provide better performance and efficiency, while still maintaining the familiar syntax of TypeScript. 6 7As mobile devices continue to become more prevalent in our daily lives, there is a growing need for programming languages optimized for the mobile environment. Many current programming languages were not designed with mobile devices in mind, resulting in slow and inefficient applications that drain battery life. ArkTS has been specifically designed to address such concerns by prioritizing higher execution efficiency. 8 9ArkTS is based on the popular programming language TypeScript that extends JavaScript by adding type definitions. TypeScript is well-loved by many developers as it provides a more structured approach to coding in JavaScript. ArkTS aims to keep the look and feel of TypeScript to enable a seamless transition for the existing TypeScript developers, and to let mobile developers learn ArkTS quickly. 10 11One of the key features of ArkTS is its focus on low runtime overhead. 12ArkTS imposes stricter limitations on the TypeScript's dynamically typed features, reducing runtime overhead and allowing faster execution. By eliminating the dynamically typed features from the language, ArkTS code can be compiled ahead-of-time more efficiently, resulting in faster application startup and lower power consumption. 13 14Interoperability with JavaScript was a critical consideration in the ArkTS language design. Many mobile app developers already have TypeScript and JavaScript code and libraries they would want to reuse. ArkTS has been designed for seamless JavaScript interoperability, making it easy for the developers to integrate the JavaScript code into their applications and vice versa. This will allow the developers to use their existing codebases and libraries to leverage the power of our new language. 15 16To ensure best experience for UI app development for OpenHarmony ecosystem, ArkTS provides support for ArkUI, including its declarative syntax and other features. Since this feature is outside the scope of the "stock" TypeScript, a verbose ArkUI example is provided in a separate chapter. 17 18This tutorial will guide you through the core features, syntax, and best practices of ArkTS. After reading this tutorial through the end, you will be able to build performant and efficient mobile applications in ArkTS. For details about programming specifications, see [ArkTS Coding Style Guide](../arkts-utils/arkts-overview.md).<!--RP1--><!--RP1End--> 19 20For a more detailed understanding of the ArkTS language, please refer to the [ArkTS Specific Guide](https://gitee.com/openharmony/docs/blob/master/en/application-dev/arkts-utils/arkts-overview.md). 21 22## The Basics 23 24### Declarations 25 26Declarations in ArkTS introduce: 27 28- Variables 29- Constants 30- Functions 31- Types 32 33#### Variable Declaration 34 35A declaration starting with the keyword `let` introduces a variable which can have different values during program execution. 36 37```typescript 38let hi: string = 'hello'; 39hi = 'hello, world'; 40``` 41 42#### Constant Declaration 43 44A declaration starting with the keyword `const` introduces a read-only constant that can be assigned only once. 45 46```typescript 47const hello: string = 'hello'; 48``` 49 50A compile-time error occurs if a new value is assigned to a constant. 51 52#### Automatic Type Inference 53 54As ArkTS is a statically typed language, the types of all entities, like variables and constants, have to be known at compile time. 55 56However, developers do not need to explicitly specify the type of a declared entity if a variable or a constant declaration contains an initial value. 57 58All cases that allow the type to be inferred automatically are specified in the ArkTS Specification. 59 60Both variable declarations are valid, and both variables are of the `string` type: 61 62```typescript 63let hi1: string = 'hello'; 64let hi2 = 'hello, world'; 65``` 66 67### Types 68 69#### Numeric Types 70 71ArkTS has numeric types. Any integer and floating-point values can be assigned to a variable of these types. 72 73Numeric literals include integer literals and floating-point literals 74with the decimal base. 75 76Integer literals include the following: 77 78* Decimal integers that consist of a sequence of digits. For example: `0`, `117`, `-345`. 79* Hexadecimal integers that start with 0x (or 0X), and can contain digits (0-9) and letters a-f or A-F. For example: `0x1123`, `0x00111`, `-0xF1A7`. 80* Octal integers that start with 0o (or 0O) and can only contain digits (0-7). For example: `0o777`. 81* Binary integers that start with 0b (or 0B), and can only contain the digits 0 and 1. For example: `0b11`, `0b0011`, `-0b11`. 82 83A floating-point literal includes the following: 84 85* Decimal integer, optionally signed (i.e., prefixed with "+" or "-"); 86* Decimal point ("."). 87* Fractional part (represented by a string of decimal digits). 88* Exponent part that starts with "e" or "E", followed by an optionally signed (i.e., prefixed with "+" or "-") integer. 89 90Example: 91 92```typescript 93let n1 = 3.14; 94let n2 = 3.141592; 95let n3 = .5; 96let n4 = 1e2; 97 98function factorial(n: number): number { 99 if (n <= 1) { 100 return 1; 101 } 102 return n * factorial(n - 1); 103} 104 105factorial(n1) // 7.660344000000002 106factorial(n2) // 7.680640444893748 107factorial(n3) // 1 108factorial(n4) // 9.33262154439441e+157 109``` 110 111The number type tends to lose precision when it represents very large integers. You can use BigInt to ensure the precision as required. 112 113```typescript 114 115let bigIntger: BigInt = BigInt('999999999999999999999999999999999999999999999999999999999999'); 116console.log('bigIntger' + bigIntger.toString()); 117 118``` 119 120#### `Boolean` 121 122The `boolean` type represents logical values that are either `true` or `false`. 123 124Usually variables of this type are used in conditional statements: 125 126```typescript 127let isDone: boolean = false; 128 129// ... 130 131if (isDone) { 132 console.log ('Done!'); 133} 134``` 135 136#### `String` 137 138A `string` is a sequence of characters; some characters can be set by using escape sequences. 139 140A `string` literal consists of zero or more characters enclosed in single (') or double quotes ("). The special form of string literals are template literals enclosed in backtick quotes (\`). 141 142```typescript 143let s1 = 'Hello, world!\n'; 144let s2 = 'this is a string'; 145let a = 'Success'; 146let s3 = `The result is ${a}`; 147``` 148 149#### `Void` Type 150 151The `void` type is used to specify that a function does not return a value. 152This type has the only one value which is also `void`. As `void` is 153a reference type, it can be used as type argument for generic types. 154 155```typescript 156class Class<T> { 157 //... 158} 159let instance: Class <void> 160``` 161 162#### `Object` Type 163 164An `Object` class type is a base type for all reference types. Any value, including values of primitive types (they will be automatically boxed), can be directly assigned to variables of the type `Object`.`The 'object' type is used to represent types other than the primitive types. 165 166#### `Array` Type 167 168An `array` is an object comprised of elements of data types assignable to the element type specified in the array declaration. 169A value of an `array` is set by using *array composite literal*, that is a list of zero or more expressions enclosed in square brackets ([]). Each expression represents an element of the `array`. The length of the `array` is set by the number of expressions. Index of the first array element is 0. 170 171The following example creates the `array` with three elements: 172 173```typescript 174let names: string[] = ['Alice', 'Bob', 'Carol']; 175``` 176 177#### `Enum` Type 178 179An `enum` type is a value type with a defined set of named values called enum constants. 180In order to be used, an `enum` constant must be prefixed with an enum `type` name. 181 182```typescript 183enum ColorSet { Red, Green, Blue } 184let c: ColorSet = ColorSet.Red; 185``` 186 187A constant expression can be used to explicitly set the value of an `enum` constant. 188 189```typescript 190enum ColorSet { White = 0xFF, Grey = 0x7F, Black = 0x00 } 191let c: ColorSet = ColorSet.Black 192``` 193 194#### `Union` Type 195 196A `union` type is a reference type which is created as a combination of other types. Values of union types can be valid values of all types a union was created from. 197 198```typescript 199class Cat { 200 name: string = 'cat'; 201 // ... 202} 203class Dog { 204 name: string = 'dog'; 205 // ... 206} 207class Frog { 208 name: string = 'frog'; 209 // ... 210} 211type Animal = Cat | Dog | Frog | number 212// Cat, Dog, and Frog are some types (class or interface ones) 213 214let animal: Animal = new Cat(); 215animal = new Frog(); 216animal = 42; 217// One may assign the variable of the union type with any valid value 218``` 219 220There are different mechanisms to get a value of a particular type from a union. 221 222Example: 223 224```typescript 225class Cat { sleep () {}; meow () {} } 226class Dog { sleep () {}; bark () {} } 227class Frog { sleep () {}; leap () {} } 228 229type Animal = Cat | Dog | Frog; 230 231function foo(animal: Animal) { 232 if (animal instanceof Frog) { 233 animal.leap(); // animal is of type Frog here 234 } 235 animal.sleep(); // Any animal can sleep 236} 237``` 238 239#### Type `Aliases` 240 241Type `aliases` provides names for anonymous types (array, function, object literal or union types) or alternative names for existing types. 242 243```typescript 244type Matrix = number[][]; 245type Handler = (s: string, no: number) => string; 246type Predicate <T> = (x: T) => boolean; 247type NullableObject = Object | null; 248``` 249 250### Operators 251 252#### Assignment Operators 253 254Simple assignment operator '=' is used as in "x = y". 255 256Compound assignment operators combine an assignment with an operator, where `x op = y` equals `x = x op y`. 257 258Compound assignment operators are as follows: `+=`, `-=`, `*=`, `/=`, `%=`, `<<=`, `>>=`, `>>>=`, `&=`, `|=`, `^=`. 259 260#### Comparison Operators 261 262| Operator | Description | 263| -------- | ------------------------------------------------------------ | 264| `===` | Returns true if both operands are strict equal. | 265| `!==` | Returns true if both operands are nots trict equal. | 266| `==` | Returns true if both operands are equal. | 267| `!=` | Returns true if both operands are not equal. | 268| `>` | Returns true if the left operand is greater than the right. | 269| `>=` | Returns true if the left operand is greater than or equal to the right. | 270| `<` | Returns true if the left operand is less than the right. | 271| `<=` | Returns true if the left operand is less than or equal to the right. | 272#### Arithmetic Operators 273 274Unary operators are `-`, `+`, `--` and `++`. 275 276Binary operators are as follows: 277 278| Operator | Description | 279|------------|--------------------------| 280| `+` | addition | 281| `-` | subtraction | 282| `*` | multiplication | 283| `/` | division | 284| `%` | remainder after division | 285#### Bitwise Operators 286 287| Operator | Description | 288|------------|-----------------------------------------------------------------------------------------------------------------| 289| `a & b` | Bitwise AND: sets each bit to 1 if the corresponding bits of both operands are 1, otherwise to 0. | 290| `a \| b` | Bitwise OR: sets each bit to 1 if at least one of the corresponding bits of both operands is 1, otherwise to 0. | 291| `a ^ b` | Bitwise XOR: sets each bit to 1 if the corresponding bits of both operands are different, otherwise to 0. | 292| `~ a` | Bitwise NOT: inverts the bits of the operand. | 293| `a << b` | Shift left: shifts the binary representation of *a* to the left by *b* bits. | 294| `a >> b` | Arithmetic right shift: shifts the binary representation of *a* to the right by *b* bits with sign-extension. | 295| `a >>> b` | Logical right shift: shifts the binary representation of *a* to the right by *b* bits with zero-extension. | 296#### Logical Operators 297 298| Operator | Description | 299|------------|---------------| 300| `a && b` | Logical AND | 301| `a \|\| b` | Logical OR | 302| `! a` | Logical NOT | 303### Statements 304 305#### `If` Statements 306 307An `if` statement is used to execute a sequence of statements when a logical condition is `true`, or another set of statements (if provided) otherwise. 308 309The `else` part can also contain more `if` statements. 310 311An `if` statement looks as follows: 312 313```typescript 314if (condition1) { 315 // statements1 316} else if (condition2) { 317 // statements2 318} else { 319 // else_statements 320} 321``` 322 323All conditional expressions must be of the type `boolean` or other types (`string`, `number`, etc.). For types other than `boolean`, implicit conversion rules apply: 324 325```typescript 326let s1 = 'Hello'; 327if (s1) { 328 console.log(s1); // prints 'Hello' 329} 330 331let s2 = 'World'; 332if (s2.length != 0) { 333 console.log(s2); // prints 'World' 334} 335``` 336 337#### `Switch` Statements 338 339A `switch` statement is used to execute a sequence of statements that match the value of a switch expression. 340 341A `switch` statement looks as follows: 342 343```typescript 344switch (expression) { 345 case label1: // will be executed if label1 is matched 346 // ... 347 // statements1 348 // ... 349 break; // Can be omitted 350 case label2: 351 case label3: // will be executed if label2 or label3 is matched 352 // ... 353 // statements23 354 // ... 355 break; // Can be omitted 356 default: 357 // default_statements 358} 359``` 360 361If the value of a `switch` expression equals the value of some label, then the corresponding statements are executed. 362 363If there is no match, and the `switch` has the default clause, then the default statements are executed. 364 365An optional `break` statement allows you to break out of the `switch` and continue executing the statement that follows the `switch`. 366 367If there is no `break`, then the next statements in the `switch` are executed. 368 369#### Conditional Expressions 370 371The conditional expression `? :` uses the `boolean` value of the first expression to decide which of two other expressions to evaluate. 372 373A conditional expression looks as follows: 374 375```typescript 376condition ? expression1 : expression2 377``` 378 379If that logical expression is truthy (a value that is considered `true`), then the first expression is used as the result of the ternary expression; otherwise, the second expression is used. 380 381Example: 382 383```typescript 384let message = Math.random() > 0.5 ? 'Valid' : 'Failed'; 385``` 386 387#### `For` Statements 388 389A `for` statement is executed repeatedly until the specified loop exit condition is `false`. 390 391A `for` statement looks as follows: 392 393```typescript 394for ([init]; [condition]; [update]) { 395 statements 396} 397``` 398 399When a `for` statement is executed, the following process takes place: 400 4011. An `init` expression is executed, if any. This expression usually initializes one or more loop counters. 4022. The condition is evaluated. If the value of condition is truthy(a value that is considered `true`), or if the conditional expression is omitted, then the statements in the `for` body are to be executed. If the value of condition is falsy(a value that is considered `false`), then the `for` loop terminates. 4033. The statements of the `for` body are executed. 4044. If there is an `update` expression, then the `update` expression is executed. 4055. Go back to step 2. 406 407Example: 408 409```typescript 410let sum = 0; 411for (let i = 0; i < 10; i += 2) { 412 sum += i; 413} 414``` 415 416#### `For-of` Statements 417 418`for-of` statements are used to iterate over an array or string. 419 420A `for-of` statement looks as follows: 421 422```typescript 423for (forVar of expression) { 424 statements 425} 426``` 427 428Example: 429 430```typescript 431for (let ch of 'a string object') { 432 /* process ch */ 433} 434``` 435 436#### `While` Statements 437 438A `while` statement has its body statements executed as long as the specified condition evaluates to `true`. 439 440A `while` statement looks as follows: 441 442```typescript 443while (condition) { 444 statements 445} 446``` 447 448Example: 449 450```typescript 451let n = 0; 452let x = 0; 453while (n < 3) { 454 n++; 455 x += n; 456} 457``` 458 459#### `Do-while` Statements 460 461`do-while` statements are executed repetitively until a specified condition evaluates to `false`. 462 463A `do-while` statement looks as follows: 464 465```typescript 466do { 467 statements 468} while (condition) 469``` 470 471Example: 472 473```typescript 474let i = 0; 475do { 476 i += 1; 477} while (i < 10) 478``` 479 480#### `Break` Statements 481 482A `break` statement is used to terminate any `loop` statement or `switch`. 483 484Example: 485 486```typescript 487let x = 0; 488while (true) { 489 x++; 490 if (x > 5) { 491 break; 492 } 493} 494``` 495 496A `break` statement with a label identifier transfers control out of the enclosing statement to the one which has the same label identifier. 497 498Example: 499 500```typescript 501let x = 1; 502label: while (true) { 503 switch (x) { 504 case 1: 505 // statements 506 break label; // breaks the while 507 } 508} 509``` 510 511#### `Continue` Statements 512 513A `continue` statement stops the execution of the current loop iteration and passes control to the next iteration. 514 515Example: 516 517```typescript 518let sum = 0; 519for (let x = 0; x < 100; x++) { 520 if (x % 2 == 0) { 521 continue; 522 } 523 sum += x; 524} 525``` 526 527#### `Throw` and `Try` Statements 528 529A `throw` statement is used to throw an exception or an error: 530 531```typescript 532throw new Error('this error') 533``` 534 535A `try` statement is used to catch and handle an exception or an error: 536 537```typescript 538try { 539 // try block 540} catch (e) { 541 // handle the situation 542} 543``` 544 545The example below shows the `throw` and `try` statements used to handle the zero division case: 546 547```typescript 548class ZeroDivisor extends Error {} 549 550function divide (a: number, b: number): number{ 551 if (b == 0) throw new ZeroDivisor(); 552 return a / b; 553} 554 555function process (a: number, b: number) { 556 try { 557 let res = divide(a, b); 558 console.log('result: ' + res); 559 } catch (x) { 560 console.log('some error'); 561 } 562} 563``` 564 565`finally` clause is also supported: 566 567```typescript 568function processData(s: string) { 569 let error: Error | null = null; 570 571 try { 572 console.log('Data processed: ' + s); 573 // ... 574 // Throwing operations 575 // ... 576 } catch (e) { 577 error = e as Error; 578 // ... 579 // More error handling 580 // ... 581 } finally { 582 if (error != null) { 583 console.log(`Error caught: input='${s}', message='${error.message}'`); 584 } 585 } 586} 587``` 588 589## Functions 590 591### Function Declarations 592 593A function declaration introduces a named function, specifying its name, parameters, return type and body. 594 595Below is a simple function with two string parameters and string return type: 596 597```typescript 598function add(x: string, y: string): string { 599 let z: string = `${x} ${y}`; 600 return z; 601} 602``` 603 604For every parameter its type annotation must be specified. 605An optional parameter allows you to omit the corresponding argument when calling a function. The last parameter of a function can be a rest parameter. 606 607### Optional Parameters 608 609An optional parameter has the form `name?: Type`. 610 611```typescript 612function hello(name?: string) { 613 if (name == undefined) { 614 console.log('Hello!'); 615 } else { 616 console.log(`Hello, ${name}!`); 617 } 618} 619``` 620 621Another form contains an expression that specifies a default value. 622If the corresponding argument to such parameter is omitted in a function call, then this parameter's value is default. 623 624```typescript 625function multiply(n: number, coeff: number = 2): number { 626 return n * coeff; 627} 628multiply(2); // returns 2*2 629multiply(2, 3); // returns 2*3 630``` 631 632### The Rest Parameter 633 634The last parameter of a function can be a rest parameter. It allows functions or methods to take unlimited number of arguments. 635 636```typescript 637function sum(...numbers: number[]): number { 638 let res = 0; 639 for (let n of numbers) 640 res += n; 641 return res; 642} 643 644sum(); // returns 0 645sum(1, 2, 3); // returns 6 646``` 647 648### Return Types 649 650If function return type can be inferred from its body content, then it can be omitted from the function declaration. 651 652```typescript 653// Explicit return type 654function foo(): string { return 'foo'; } 655 656// Implicit return type inferred as string 657function goo() { return 'goo'; } 658``` 659 660The return type of a function that does not need to return a value can be explicitly specified as `void` or omitted altogether. No return statement is needed for such functions. 661 662Both notations below are valid: 663 664```typescript 665function hi1() { console.log('hi'); } 666function hi2(): void { console.log('hi'); } 667``` 668 669### Function Scope 670 671Variables and other entities defined in a function are local to the function and cannot be accessed from the outside. 672 673If the name of a variable defined in the function is equal to the name of an entity in the outer scope, then the local definition shadows the outer entity. 674 675### Function Calls 676 677Calling a function actually leads to the execution of its body, while the arguments of the call are assigned to the function parameters. 678 679If the function is defined as follows: 680 681```typescript 682function join(x: string, y: string): string { 683 let z: string = `${x} ${y}`; 684 return z; 685} 686``` 687 688then it is called with two arguments of the type `string`: 689 690```typescript 691let x = join('hello', 'world'); 692console.log(x); 693``` 694 695## Function Types 696 697Function types are commonly used as follows to define callbacks: 698 699```typescript 700type trigFunc = (x: number) => number // this is a function type 701 702function do_action(f: trigFunc) { 703 f(3.141592653589); // call the function 704} 705 706do_action(Math.sin); // pass the function as the parameter 707``` 708 709### Arrow Functions (Lambdas Functions) 710 711A function can be defined as an arrow function, for example: 712 713```typescript 714let sum = (x: number, y: number): number => { 715 return x + y; 716} 717``` 718 719An arrow function return type can be omitted; in such case, it is inferred from the function body. 720 721An expression can be specified as an arrow function to make the notation shorter, i.e., the following two notations are equivalent: 722 723```typescript 724let sum1 = (x: number, y: number) => { return x + y; } 725let sum2 = (x: number, y: number) => x + y 726``` 727 728### Closure 729 730A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created. 731 732In the following example, **z** is a reference to the instance of the function **g** that is created when **f** is executed. The instance of **g** maintains a reference to its lexical environment, within which the variable **count** exists. For this reason, when **z** is invoked, the variable **count** remains available for use. 733 734```typescript 735function f(): () => number { 736 let count = 0; 737 let g = (): number => { count++; return count; }; 738 return g; 739} 740 741let z = f(); 742z(); // output: 1 743z(); // output: 2 744``` 745 746### Function Overload Signatures 747 748A function can be specified to be called in different ways by writing overload signatures. To do so, several functions' headers that have the same name but different signatures are written and immediately followed by the single implementation function. 749 750```typescript 751function foo(x: number): void; /* 1st signature */ 752function foo(x: string): void; /* 2nd signature */ 753function foo(x: number | string): void { /* Implementation signature */ 754} 755 756foo(123); // ok, 1st signature is used 757foo('aa'); // ok, 2nd signature is used 758``` 759 760An error occurs if two overload signatures have identical parameter lists. 761 762## Classes 763 764A class declaration introduces a new type and defines its fields, methods and constructors. 765 766In the following example, class `Person` is defined, which has fields **name** and **surname**, constructor, and a method `fullName`: 767 768```typescript 769class Person { 770 name: string = ''; 771 surname: string = ''; 772 constructor (n: string, sn: string) { 773 this.name = n; 774 this.surname = sn; 775 } 776 fullName(): string { 777 return this.name + ' ' + this.surname; 778 } 779} 780``` 781 782After the class is defined, its instances can be created by using the keyword `new`: 783 784```typescript 785let p = new Person('John', 'Smith'); 786console.log(p.fullName()); 787``` 788 789or an instance can be created by using object literals: 790 791```typescript 792class Point { 793 x: number = 0; 794 y: number = 0; 795} 796let p: Point = {x: 42, y: 42}; 797``` 798 799### Fields 800 801A field is a variable of some type that is declared directly in a class. 802 803Classes may have instance fields, static fields or both. 804 805#### Instance Fields 806 807Instance fields exist on every instance of a class. Each instance has its own set of instance fields. 808 809An instance of the class is used to access an instance field. 810 811```typescript 812class Person { 813 name: string = ''; 814 age: number = 0; 815 constructor(n: string, a: number) { 816 this.name = n; 817 this.age = a; 818 } 819 820 getName(): string { 821 return this.name; 822 } 823} 824 825let p1 = new Person('Alice', 25); 826p1.name; 827let p2 = new Person('Bob', 28); 828p2.getName(); 829``` 830 831#### Static Fields 832 833The keyword `static` is used to declare a field as static. Static fields belong to the class itself, and all instances of the class share one static field. 834 835The class name is used to access a static field: 836 837```typescript 838class Person { 839 static numberOfPersons = 0; 840 constructor() { 841 // ... 842 Person.numberOfPersons++; 843 // ... 844 } 845} 846 847Person.numberOfPersons; 848``` 849 850#### Field Initializers 851 852ArkTS requires that all fields are explicitly initialized with some values either when the field is declared or in the `constructor`. This is similar to `strictPropertyInitialization` mode of the standard TypeScript. Such behavior is enforced to minimize the number of unexpected runtime errors and achieve better performance. 853 854The following code (invalid in ArkTS) is error-prone: 855 856```typescript 857class Person { 858 name: string; // undefined 859 860 setName(n:string): void { 861 this.name = n; 862 } 863 864 getName(): string { 865 // Return type "string" hides from the developers the fact 866 // that name can be undefined. The most correct would be 867 // to write the return type as "string | undefined". By doing so 868 // we tell the users of our API about all possible return values. 869 return this.name; 870 } 871} 872 873let jack = new Person(); 874// Let's assume that the developer forgets to call setName: 875// jack.setName('Jack') 876jack.getName().length; // runtime exception: name is undefined 877``` 878 879Here is how it should look in ArkTS: 880 881```typescript 882class Person { 883 name: string = ''; 884 885 setName(n:string): void { 886 this.name = n; 887 } 888 889 // The type is always string, no other "hidden options". 890 getName(): string { 891 return this.name; 892 } 893} 894 895 896let jack = new Person(); 897// Let's assume that the developer forgets to call setName: 898// jack.setName('Jack') 899jack.getName().length; // 0, no runtime error 900``` 901 902And here how our code behaves if the field `name` can be `undefined` 903 904```typescript 905class Person { 906 name?: string; // The field may be undefined 907 908 setName(n:string): void { 909 this.name = n; 910 } 911 912 // Compile-time error: 913 // name can be "undefined", so we cannot say to those who use this API 914 // that it returns only strings: 915 getNameWrong(): string { 916 return this.name; 917 } 918 919 getName(): string | undefined { // Return type matches the type of name 920 return this.name; 921 } 922} 923 924let jack = new Person() 925// Let's assume that the developer forgets to call setName: 926// jack.setName('Jack') 927 928// Compile-time(!) error: Compiler suspects that we 929// may possibly access something undefined and won't build the code: 930jack.getName().length; // The code won't build and run 931 932jack.getName()?.length; // Builds ok, no runtime error 933``` 934 935#### Getters and Setters 936 937Setters and getters can be used to provide controlled access to object properties. 938 939In the following example, a setter is used to forbid setting invalid values of the '_age' property: 940 941```typescript 942class Person { 943 name: string = ''; 944 private _age: number = 0; 945 get age(): number { return this._age; } 946 set age(x: number) { 947 if (x < 0) { 948 throw Error('Invalid age argument'); 949 } 950 this._age = x; 951 } 952} 953 954let p = new Person(); 955p.age; // 0 956p.age = -42; // Error will be thrown as an attempt to set incorrect age 957``` 958 959A class can define a getter, a setter or both. 960 961### Methods 962 963A method is a function that belongs to a class. 964A class can define instance methods, static methods or both. 965A static method belongs to the class itself, and can have access to static fields only. 966A `while` instance method has access to both static (class) fields and instance fields including private ones of its class. 967 968### Instance Methods 969 970The example below illustrates how instanced methods work. 971The `calculateArea` method calculates the area of a rectangle by multiplying the height by the width: 972 973```typescript 974class RectangleSize { 975 private height: number = 0; 976 private width: number = 0; 977 constructor(height: number, width: number) { 978 this.height = height; 979 this.width = width; 980 } 981 calculateArea(): number { 982 return this.height * this.width; 983 } 984} 985``` 986 987To use an instance method, it must be called on an instance of the class: 988 989```typescript 990let square = new RectangleSize(10, 10); 991square.calculateArea(); // output: 100 992``` 993 994#### Static Methods 995 996The keyword `static` is used to declare a method as static. Static methods belong to the class itself and have access to static fields only. 997A static method defines a common behavior of the class as a whole. 998 999The class name is used to call a static method: 1000 1001```typescript 1002class Cl { 1003 static staticMethod(): string { 1004 return 'this is a static method.'; 1005 } 1006} 1007console.log(Cl.staticMethod()); 1008``` 1009 1010#### Inheritance 1011 1012A class can extend another class. 1013The class that is being extended by another class is called ‘*base class*’, ‘parent class’, or ‘superclass’. 1014The class that extends another class is called ‘*extended class*’, ‘derived class’, or ‘subclass’. 1015 1016An extended class can implement several interfaces by using the following syntax: 1017 1018```typescript 1019class [extends BaseClassName] [implements listOfInterfaces] { 1020 // ... 1021} 1022``` 1023 1024An extended class inherits fields and methods, but not constructors from the base class, and can add its own fields and methods, as well as override methods defined by the base class. 1025 1026Example: 1027 1028```typescript 1029class Person { 1030 name: string = ''; 1031 private _age = 0; 1032 get age(): number { 1033 return this._age; 1034 } 1035} 1036class Employee extends Person { 1037 salary: number = 0; 1038 calculateTaxes(): number { 1039 return this.salary * 0.42; 1040 } 1041} 1042``` 1043 1044A class containing the `implements` clause must implement all methods defined in all listed interfaces, except the methods defined with default implementation. 1045 1046```typescript 1047interface DateInterface { 1048 now(): string; 1049} 1050class MyDate implements DateInterface { 1051 now(): string { 1052 // implementation is here 1053 return 'now'; 1054 } 1055} 1056``` 1057 1058#### Access to Super 1059 1060The keyword `super` can be used to access instance fields, instance methods and constructors from the super class. 1061 1062It is often used to extend basic functionality of subclass with the required behavior taken from the super class: 1063 1064```typescript 1065class RectangleSize { 1066 protected height: number = 0; 1067 protected width: number = 0; 1068 1069 constructor (h: number, w: number) { 1070 this.height = h; 1071 this.width = w; 1072 } 1073 1074 draw() { 1075 /* draw bounds */ 1076 } 1077} 1078class FilledRectangle extends RectangleSize { 1079 color = '' 1080 constructor (h: number, w: number, c: string) { 1081 super(h, w); // call of super constructor 1082 this.color = c; 1083 } 1084 1085 draw() { 1086 super.draw(); // call of super methods 1087 // super.height - can be used here 1088 /* fill rectangle */ 1089 } 1090} 1091``` 1092 1093#### Override Methods 1094 1095A subclass can override implementation of a method defined in its superclass. 1096An overridden method must have the same types of parameters, and same or derived return type as the original method. 1097 1098```typescript 1099class RectangleSize { 1100 // ... 1101 area(): number { 1102 // implementation 1103 return 0; 1104 } 1105} 1106class Square extends RectangleSize { 1107 private side: number = 0; 1108 area(): number { 1109 return this.side * this.side; 1110 } 1111} 1112``` 1113 1114#### Method Overload Signatures 1115 1116A method can be specified to be called in different ways by writing overload signatures. To do so, several method headers that have the same name but different signatures are written and immediately followed by the single implementation method. 1117 1118```typescript 1119class C { 1120 foo(x: number): void; /* 1st signature */ 1121 foo(x: string): void; /* 2nd signature */ 1122 foo(x: number | string): void { /* implementation signature */ 1123 } 1124} 1125let c = new C(); 1126c.foo(123); // ok, 1st signature is used 1127c.foo('aa'); // ok, 2nd signature is used 1128``` 1129 1130An error occurs if two overload signatures have the same name and identical parameter lists. 1131 1132### Constructors 1133 1134A class declaration may contain a constructor that is used to initialize object state. 1135 1136A constructor is defined as follows: 1137 1138```typescript 1139constructor ([parameters]) { 1140 // ... 1141} 1142``` 1143 1144If no constructor is defined, then a default constructor with an empty parameter list is created automatically, for example: 1145 1146```typescript 1147class Point { 1148 x: number = 0; 1149 y: number = 0; 1150} 1151let p = new Point(); 1152``` 1153 1154In this case the default constructor fills the instance fields with default values for the field types. 1155 1156#### Constructors in Derived Class 1157 1158The first statement of a constructor body can use the keyword `super` to explicitly call a constructor of the direct superclass. 1159 1160```typescript 1161class RectangleSize { 1162 constructor(width: number, height: number) { 1163 // ... 1164 } 1165} 1166class Square extends RectangleSize { 1167 constructor(side: number) { 1168 super(side, side); 1169 } 1170} 1171``` 1172 1173#### Constructor Overload Signatures 1174 1175A constructor can be specified to be called in different ways by writing overload signatures. To do so, several constructor headers that have the same name but different signatures are written and immediately followed by the single implementation constructor. 1176 1177```typescript 1178class C { 1179 constructor(x: number) /* 1st signature */ 1180 constructor(x: string) /* 2nd signature */ 1181 constructor(x: number | string) { /* Implementation signature */ 1182 } 1183} 1184let c1 = new C(123); // ok, 1st signature is used 1185let c2 = new C('abc'); // ok, 2nd signature is used 1186``` 1187 1188An error occurs if two overload signatures have the same name and identical parameter lists. 1189 1190### Visibility Modifiers 1191 1192Both methods and properties of a class can have visibility modifiers. 1193 1194There are several visibility modifiers: 1195 1196- `private` 1197- `protected` 1198- `public` 1199 1200The default visibility is `public`. 1201 1202#### Public Visibility 1203 1204The `public` members (fields, methods, constructors) of a class are visible in any part of the program, where their class is visible. 1205 1206### Private Visibility 1207 1208A `private` member cannot be accessed outside the class it is declared in. 1209Example: 1210 1211```typescript 1212class C { 1213 public x: string = ''; 1214 private y: string = ''; 1215 set_y (new_y: string) { 1216 this.y = new_y // ok, as y is accessible within the class itself 1217 } 1218} 1219let c = new C(); 1220c.x = 'a'; // ok, the field is public 1221c.y = 'b'; // compile-time error: 'y' is not visible 1222``` 1223 1224#### Protected Visibility 1225 1226The modifier `protected` acts much like the modifier `private`, but the `protected` members are also accessible in derived classes. 1227Example: 1228 1229```typescript 1230class Base { 1231 protected x: string = ''; 1232 private y: string = ''; 1233} 1234class Derived extends Base { 1235 foo() { 1236 this.x = 'a'; // ok, access to protected member 1237 this.y = 'b'; // compile-time error, 'y' is not visible, as it is private 1238 } 1239} 1240``` 1241 1242### Object Literals 1243 1244An object literal is an expression that can be used to create a class instance and provide some initial values. It can be used instead of the expression `new` as it is more convenient in some cases. 1245 1246A class composite is written as a comma-separated list of name-value pairs enclosed in '{' and '}'. 1247 1248```typescript 1249class C { 1250 n: number = 0; 1251 s: string = ''; 1252} 1253 1254let c: C = {n: 42, s: 'foo'}; 1255``` 1256 1257Due to the static typing of the ArkTS, object literals can be used in a context where the class or interface type of the object literal can be inferred as in the example above. Other valid cases are illustrated below: 1258 1259```typescript 1260class C { 1261 n: number = 0; 1262 s: string = ''; 1263} 1264 1265function foo(c: C) {} 1266 1267let c: C; 1268 1269c = {n: 42, s: 'foo'}; // type of the variable is used 1270foo({n: 42, s: 'foo'}); // type of the parameter is used 1271 1272function bar(): C { 1273 return {n: 42, s: 'foo'}; // return type is used 1274} 1275``` 1276 1277The type of an array element or of a class field can also be used: 1278 1279```typescript 1280class C { 1281 n: number = 0; 1282 s: string = ''; 1283} 1284let cc: C[] = [{n: 1, s: 'a'}, {n: 2, s: 'b'}]; 1285``` 1286 1287#### Object Literals of Record Type 1288 1289The generic Record<K, V> type is used to map the properties of a type (Key type) to another type (Value type). 1290 1291A special form of object literal is used to initialize the value of such type: 1292 1293```typescript 1294let map: Record<string, number> = { 1295 'John': 25, 1296 'Mary': 21, 1297} 1298 1299map['John']; // 25 1300``` 1301 1302The K type can be either string or number, while V can be any type. 1303 1304```typescript 1305interface PersonInfo { 1306 age: number; 1307 salary: number; 1308} 1309let map: Record<string, PersonInfo> = { 1310 'John': { age: 25, salary: 10}, 1311 'Mary': { age: 21, salary: 20} 1312} 1313``` 1314 1315### Abstract Classes 1316 1317A class with the modifier abstract is known as abstract class. Abstract classes can be used to represent notions that are common to some set of more concrete notions. 1318 1319A compile-time error occurs if an attempt is made to create an instance of an abstract class: 1320 1321```typescript 1322abstract class X { 1323 field: number; 1324 constructor(p: number) { 1325 this.field = p; 1326 } 1327} 1328 1329let x = new X(666) // Compile-time error: Cannot create an instance of an abstract class. 1330``` 1331 1332Subclasses of an abstract class can be non-abstract or in turn abstract. A non-abstract subclass of an abstract superclass can be instantiated. As a result, a constructor for the abstract class, and field initializers for non-static fields of that class are executed: 1333 1334```typescript 1335abstract class Base { 1336 field: number; 1337 constructor(p: number) { 1338 this.field = p; 1339 } 1340} 1341 1342class Derived extends Base { 1343 constructor(p: number) { 1344 super(p); 1345 } 1346} 1347``` 1348 1349#### Abstract Methods 1350 1351A method with the modifier abstract is considered an abstract method. Abstract methods do not have bodies, i.e., they can be declared but not implemented. 1352 1353Only abstract classes can have abstract methods. A compile-time error occurs if a non-abstract class has an abstract method: 1354 1355```typescript 1356class Y { 1357 abstract method(p: string) //Compile-time error: Abstract methods can only appear within an abstract class. 1358} 1359``` 1360 1361## Interfaces 1362 1363An interface declaration introduces a new type. Interfaces are a common way of defining contracts between various part of codes. 1364 1365Interfaces are used to write polymorphic code, which can be applied to any class instances that implement a particular interface. 1366 1367An interface usually contains properties and method headers. 1368 1369Examples: 1370 1371```typescript 1372interface Style { 1373 color: string; // property 1374} 1375interface AreaSize { 1376 calculateAreaSize(): number; // method header 1377 someMethod(): void; // method header 1378} 1379``` 1380 1381Examples of a class implementing an interface: 1382 1383```typescript 1384// Interface: 1385interface AreaSize { 1386 calculateAreaSize(): number; // method header 1387 someMethod(): void; // method header 1388} 1389 1390// Implementation: 1391class RectangleSize implements AreaSize { 1392 private width: number = 0; 1393 private height: number = 0; 1394 someMethod(): void { 1395 console.log('someMethod called'); 1396 } 1397 calculateAreaSize(): number { 1398 this.someMethod(); // calls another method and returns result 1399 return this.width * this.height; 1400 } 1401} 1402``` 1403 1404### Interface Properties 1405 1406An interface property can be in a form of field, getter, setter, or both getter and setter. 1407 1408A property field is just a shortcut notation of a getter/setter pair, and the following notations are equal: 1409 1410```typescript 1411interface Style { 1412 color: string; 1413} 1414``` 1415 1416```typescript 1417interface Style { 1418 get color(): string 1419 set color(x: string) 1420} 1421``` 1422 1423A class that implements an interface may also use a short or a long notation: 1424 1425```typescript 1426interface Style { 1427 color: string; 1428} 1429 1430class StyledRectangle implements Style { 1431 color: string = ''; 1432} 1433``` 1434 1435```typescript 1436interface Style { 1437 color: string; 1438} 1439 1440class StyledRectangle implements Style { 1441 private _color: string = ''; 1442 get color(): string { return this._color; } 1443 set color(x: string) { this._color = x; } 1444} 1445``` 1446 1447### Interface Inheritance 1448 1449An interface may extend other interfaces like in the example below: 1450 1451```typescript 1452interface Style { 1453 color: string; 1454} 1455 1456interface ExtendedStyle extends Style { 1457 width: number; 1458} 1459``` 1460 1461An extended interface contains all properties and methods of the interface it extends, and can also add its own properties and methods. 1462 1463 1464### Abstract class and interface 1465 1466Abstract classes and interfaces cannot be instantiated. Abstract classes are abstractions of classes, used to capture the general characteristics of subclasses, and interfaces are abstractions of behavior. The difference between abstract classes and interfaces in ArkTS is as follows: 1467 1468* Abstract classes can only inherit from a single source, while interfaces can be implemented in multiple layers; 1469* In abstract classes, there can be implementations of methods, but interfaces are completely abstract and there is no implementation of methods; 1470* The interface cannot contain static code blocks and static methods, while abstract classes can have static code blocks and static functions; 1471* Abstract classes can have constructors, while interfaces cannot have constructors. 1472 1473## Generic Types and Functions 1474 1475Generic types and functions allow creating the code capable to work over a variety of types rather than a single type. 1476 1477### Generic Classes and Interfaces 1478 1479A class and an interface can be defined as generics, adding parameters to the type definition, like the type parameter `Element` in the following example: 1480 1481```typescript 1482class CustomStack<Element> { 1483 public push(e: Element):void { 1484 // ... 1485 } 1486} 1487``` 1488 1489To use type CustomStack, the type argument must be specified for each type parameter: 1490 1491```typescript 1492let s = new CustomStack<string>(); 1493s.push('hello'); 1494``` 1495 1496Compiler ensures type safety while working with generic types and functions. 1497See below: 1498 1499```typescript 1500let s = new CustomStack<string>(); 1501s.push(55); // That will be a compile-time error as 55 is not compatible with type string. 1502``` 1503 1504### Generic Constraints 1505 1506Type parameters of generic types can be bounded. For example, the `Key` type parameter in the `MyHashMap<Key, Value>` container must have the `hash` method. 1507 1508```typescript 1509interface Hashable { 1510 hash(): number; 1511} 1512class MyHashMap<Key extends Hashable, Value> { 1513 public set(k: Key, v: Value) { 1514 let h = k.hash(); 1515 // ... other code ... 1516 } 1517} 1518``` 1519 1520In the above example, the `Key` type extends `Hashable`, and all methods of `Hashable` interface can be called for keys. 1521 1522### Generic Functions 1523 1524Use a generic function to create a more universal code. Consider a function that returns the last element of the array: 1525 1526```typescript 1527function last(x: number[]): number { 1528 return x[x.length - 1]; 1529} 1530last([1, 2, 3]); // output: 3 1531``` 1532 1533If the same function needs to be defined for any array, then define it as a generic with a type parameter: 1534 1535```typescript 1536function last<T>(x: T[]): T { 1537 return x[x.length - 1]; 1538} 1539``` 1540 1541Now, the function can be used with any array. 1542 1543In a function call, type argument can be set explicitly or implicitly: 1544 1545```typescript 1546// Explicit type argument 1547last<string>(['aa', 'bb']); 1548last<number>([1, 2, 3]); 1549 1550// Implicit type argument: 1551// Compiler understands the type argument based on the type of the call arguments 1552last([1, 2, 3]); 1553``` 1554 1555### Generic Defaults 1556 1557Type parameters of generic types can have defaults. It allows using just the generic type name instead of specifying the actual type arguments. 1558The example below illustrates this for both classes and functions. 1559 1560```typescript 1561class SomeType {} 1562interface Interface <T1 = SomeType> { } 1563class Base <T2 = SomeType> { } 1564class Derived1 extends Base implements Interface { } 1565// Derived1 is semantically equivalent to Derived2 1566class Derived2 extends Base<SomeType> implements Interface<SomeType> { } 1567 1568function foo<T = number>(): T { 1569 // ... 1570} 1571foo(); 1572// such function is semantically equivalent to the call below 1573foo<number>(); 1574``` 1575 1576## Null Safety 1577 1578All types in ArkTS by default are non-nullable, so the value of a type cannot be null. 1579It is similar to TypeScript behavior in strict null checking mode (`strictNullChecks`), but the rules are stricter. 1580 1581In the example below, all lines cause a compile-time error: 1582 1583```typescript 1584let x: number = null; // Compile-time error 1585let y: string = null; // Compile-time error 1586let z: number[] = null; // Compile-time error 1587``` 1588 1589A variable that can have a null value is defined with a union type `T | null`. 1590 1591```typescript 1592let x: number | null = null; 1593x = 1; // ok 1594x = null; // ok 1595if (x != null) { /* do something */ } 1596``` 1597 1598### Non-Null Assertion Operator 1599 1600A postfix operator `!` can be used to assert that its operand is non-null. 1601 1602If applied to a null value, the operator throws an error. Otherwise, the type of the value is changed from `T | null` to `T`: 1603 1604```typescript 1605class A { 1606 value: number = 0; 1607} 1608 1609function foo(a: A | null) { 1610 a.value; // compile time error: cannot access to a nullable value 1611 1612 // ok, if the value of a is not null at runtime, the fields of a can be accessed; 1613 // If the value of runtime a is empty, a runtime exception occurs. 1614 a!.value; 1615} 1616``` 1617 1618### Null-Coalescing Operator 1619 1620The null-coalescing binary operator `??` checks whether the evaluation of the left-hand-side expression is equal to `null` or `undefined`. 1621If it is, then the result of the expression is the right-hand-side expression; otherwise, it is the left-hand-side expression. 1622 1623In other words, `a ?? b` equals the ternary operator `(a != null && a != undefined) ? a : b`. 1624 1625In the following example, the method `getNick` returns a nickname if it is set; otherwise, an empty string is returned: 1626 1627```typescript 1628class Person { 1629 // ... 1630 nick: string | null = null; 1631 getNick(): string { 1632 return this.nick ?? ''; 1633 } 1634} 1635``` 1636 1637### Optional Chaining 1638 1639Optional chaining operator `?.` allows writing code where the evaluation stops at an expression that is partially evaluated to `null` or `undefined`. 1640 1641```typescript 1642class Person { 1643 nick: string | null = null; 1644 spouse?: Person; 1645 1646 setSpouse(spouse: Person): void { 1647 this.spouse = spouse; 1648 } 1649 1650 getSpouseNick(): string | null | undefined { 1651 return this.spouse?.nick; 1652 } 1653 1654 constructor(nick: string) { 1655 this.nick = nick; 1656 this.spouse = undefined; 1657 } 1658} 1659``` 1660 1661**Note**: The return type of `getSpouseNick` must be `string | null | undefined`, as the method can return `null` or `undefined`. 1662 1663An optional chain can be of any length and contain any number of `?.` operators. 1664 1665In the following sample, the output is a person's spouse nickname if that person has a spouse, and the spouse has a nickname. 1666 1667Otherwise, the output is `undefined`: 1668 1669```typescript 1670class Person { 1671 nick: string | null = null; 1672 spouse?: Person; 1673 1674 constructor(nick: string) { 1675 this.nick = nick; 1676 this.spouse = undefined; 1677 } 1678} 1679 1680let p: Person = new Person('Alice'); 1681p.spouse?.nick; // undefined 1682``` 1683 1684## Modules 1685 1686Programs are organized as sets of compilation units or modules. 1687 1688Each module creates its own scope, i.e., any declarations (variables, functions, classes, etc.) declared in the module are not visible outside that module unless they are explicitly exported. 1689 1690Conversely, a variable, function, class, interface, etc. exported from another module must first be imported to a module. 1691 1692### Export 1693 1694A top-level declaration can be exported by using the keyword `export`. 1695 1696A declared name that is not exported is considered private and can be used only in the module where it is declared. 1697 1698 1699```typescript 1700export class Point { 1701 x: number = 0; 1702 y: number = 0; 1703 constructor(x: number, y: number) { 1704 this.x = x; 1705 this.y = y; 1706 } 1707} 1708export let Origin = new Point(0, 0); 1709export function Distance(p1: Point, p2: Point): number { 1710 return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)); 1711} 1712``` 1713 1714### Import 1715 1716#### Static Import 1717 1718Import declarations are used to import entities exported from other modules and provide their bindings in the current module. 1719An import declaration consists of two parts: 1720 1721* Import path that determines the module to import from. 1722* Import bindings that define the set of usable entities in the imported module, and the form of use (i.e., qualified or unqualified use). 1723 1724Import bindings may have several forms. 1725 1726Let's assume a module has the path './utils' and export entities 'X' and 'Y'. 1727 1728An import binding of the form `* as A` binds the name 'A', and all entities exported from the module defined by the import path can be accessed by using the qualified name `A.name`: 1729 1730```typescript 1731import * as Utils from './utils'; 1732Utils.X // denotes X from Utils 1733Utils.Y // denotes Y from Utils 1734``` 1735 1736An import binding of the form `{ ident1, ..., identN }` binds an exported entity with a specified name, which can be used as a simple name: 1737 1738```typescript 1739import { X, Y } from './utils'; 1740X // denotes X from Utils 1741Y // denotes Y from Utils 1742``` 1743 1744If a list of identifiers contains aliasing of the form `ident as alias`, then entity `ident` is bound under the name `alias`: 1745 1746```typescript 1747import { X as Z, Y } from './utils'; 1748Z // denotes X from Utils 1749Y // denotes Y from Utils 1750X // Compile-time error: 'X' is not visible 1751``` 1752#### Dynamic Import 1753Unlike static import, static import allows you to load a module conditionally or on demand. 1754The **import() **syntax, commonly called dynamic import, is a function-like expression that allows for dynamic loading of a module. It returns a promise. 1755In the following example, **import(modulePath)** loads the module and returns a promise that resolves into a module object that contains all its exports. This expression can be called from any place in the code. 1756 1757```typescript 1758// Calc.ts 1759export function add(a:number, b:number):number { 1760 let c = a + b; 1761 console.info('Dynamic import, %d + %d = %d', a, b, c); 1762 return c; 1763} 1764// Index.ts 1765import("./Calc").then((obj: ESObject) => { 1766 console.info(obj.add(3, 5)); 1767}).catch((err: Error) => { 1768 console.error("Module dynamic import error: ", err); 1769}); 1770``` 1771 1772You can also use **let module = await import(modulePath)** inside an async function. 1773 1774```typescript 1775// say.ts 1776export function hi() { 1777 console.log('Hello'); 1778} 1779export function bye() { 1780 console.log('Bye'); 1781} 1782``` 1783 1784Then dynamic import can be like this: 1785 1786```typescript 1787async function test() { 1788 let ns = await import('./say'); 1789 let hi = ns.hi; 1790 let bye = ns.bye; 1791 hi(); 1792 bye(); 1793} 1794``` 1795 1796For more details about dynamic import, see [Dynamic Import](../arkts-utils/arkts-dynamic-import.md). 1797 1798<!--RP2--><!--RP2End--> 1799 1800### Top-Level Statements 1801 1802A module can contain any statements at the module level, except `return` ones. 1803 1804## Keywords 1805 1806### this 1807 1808The keyword `this` can only be used in instance methods of a class. 1809 1810**Example** 1811 1812```typescript 1813class A { 1814 count: string = 'a'; 1815 m(i: string): void { 1816 this.count = i; 1817 } 1818} 1819``` 1820 1821Constraints: 1822 1823* Type notation using `this` is not supported. 1824* Using `this` inside standalone functions is not supported. 1825 1826**Example** 1827 1828```typescript 1829class A { 1830 n: number = 0; 1831 f1(arg1: this) {} // Compile-time error. Type notation using this is not supported. 1832 static f2(arg1: number) { 1833 this.n = arg1; // Compile-time error. Using this inside standalone functions is not supported. 1834 } 1835} 1836 1837function foo(arg1: number) { 1838 this.n = i; // Compile-time error. Using this inside standalone functions is not supported. 1839} 1840``` 1841 1842The keyword `this` used as a primary expression denotes a value that is a reference to the following: 1843 1844* Object for which the instance method is called; or 1845* Object being constructed. 1846 1847The value denoted by `this` in a lambda body and in the surrounding context is the same. 1848 1849## Support for ArkUI 1850 1851This section demonstrates mechanisms that ArkTS provides for creating graphical user interface (GUI) programs. The section is based on the ArkUI declarative framework. ArkUI provides a set of extensions of the standard TypeScript to declaratively describe the GUI of the applications and the interaction between the GUI components. 1852 1853### ArkUI Example 1854 1855The [Example](arkts-mvvm.md#example) provides a complete ArkUI-based application as an illustration of GUI programming capabilities. 1856 1857For more details of the ArkUI features, refer to the ArkUI [Basic Syntax](arkts-basic-syntax-overview.md). 1858 1859<!--no_check-->