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