1# Introduction 2 3<!--Kit: ArkTS--> 4<!--Subsystem: ArkCompiler--> 5<!--Owner: @LeechyLiang--> 6<!--Designer: @qyhuo32--> 7<!--Tester: @kirl75; @zsw_zhushiwei--> 8<!--Adviser: @zhang_yixin13--> 9 10Welcome to the tutorial for ArkTS, a TypeScript-based programming language designed specifically to build high-performance mobile applications! ArkTS is optimized to provide better performance and efficiency, while still maintaining the familiar syntax of TypeScript. 11 12Many current programming languages were not designed with mobile devices in mind, resulting in slow and inefficient applications that drain battery life. As mobile devices continue to become more prevalent in our daily lives, there is a growing need for programming languages optimized for the mobile environment. ArkTS has been specifically designed to address such concerns by prioritizing higher execution efficiency. 13 14ArkTS 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. 15 16One of the key features of ArkTS is its focus on low runtime overhead. ArkTS 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. 17 18Interoperability with TypeScript and JavaScript was a critical consideration in the ArkTS language design. Many mobile application 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. 19 20This 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. 21 22For a more detailed understanding of the ArkTS language, see [Introduction to ArkTS](../arkts-utils/arkts-overview.md)<!--RP1--><!--RP1End-->. 23 24## The Basics 25 26### Declarations 27 28Declarations in ArkTS allow you to introduce variables, constants, types, and functions. 29 30**Variable declaration** 31 32A declaration starting with the keyword `let` introduces a variable which can have different values during program execution. 33 34```typescript 35let hi: string = 'hello'; 36hi = 'hello, world'; 37``` 38 39**Constant declaration** 40 41A declaration starting with the keyword `const` introduces a read-only constant that can be assigned only once. 42 43```typescript 44const hello: string = 'hello'; 45``` 46 47A compile-time error occurs if a new value is assigned to a constant. 48 49**Automatic type inference** 50 51You do not need to explicitly specify the type of a declared entity if a variable or a constant declaration contains an initial value, as all cases that allow the type to be inferred automatically are specified in the ArkTS Specification. 52 53Both variable declarations are valid, and both variables are of the `string` type: 54 55```typescript 56let hi1: string = 'hello'; 57let hi2 = 'hello, world'; 58``` 59 60### Types 61 62**Basic types and reference types** 63 64Basic types include number and string, which can accurately represent simple data types. You can directly store and access these types and compare their values. 65 66Reference types include complex data structures such as objects, arrays, and functions. These types access data by reference. An object and array contain multiple values or KV pairs, and a function encapsulates executable code logic. The reference type accesses data in the memory through pointers. Changing the reference affects the original data. 67 68**`number` type** 69 70ArkTS has the number type. Any integer and floating-point values can be assigned to a variable of this type. 71 72Numeric literals include integer literals and floating-point literals with the decimal base. 73 74Integer literals are classified into the following: 75 76* Decimal integers consist of digit sequences.* Decimal integers that consist of a sequence of digits. Example: `0`, `117`, `-345`. 77* Hexadecimal integers that start with 0x (or 0X), and can contain digits (0-9) and letters a-f or A-F. Example: `0x1123`, `0x00111`, `-0xF1A7`. 78* Octal integers that start with 0o (or 0O) and can only contain digits (0-7). Example: `0o777`. 79* Binary integers that start with 0b (or 0B), and can only contain the digits 0 and 1. Example: `0b11`, `0b0011`, `-0b11`. 80 81A floating-point literal includes the following: 82 83* Decimal integer, optionally signed (that is, prefixed with "+" or "-") 84* Decimal point (".") 85* Fractional part (represented by a string of decimal digits) 86* Exponent part that starts with "e" or "E", followed by an optionally signed (that is, prefixed with "+" or "-") integer 87 88Example: 89 90```typescript 91let n1 = 3.14; 92let n2 = 3.141592; 93let n3 = .5; 94let n4 = 1e2; 95 96function factorial(n: number): number { 97 if (n <= 1) { 98 return 1; 99 } 100 return n * factorial(n - 1); 101} 102 103factorial(n1) // 7.660344000000002 104factorial(n2) // 7.680640444893748 105factorial(n3) // 1 106factorial(n4) // 9.33262154439441e+157 107``` 108 109The `number` type tends to lose precision when it represents very large integers (ranging from -9007199254740991 to 9007199254740991). You can use the `bigint` type to ensure the precision as required. 110 111```typescript 112 113let bigInt: BigInt = BigInt('999999999999999999999999999999999999999999999999999999999999'); 114console.info('bigInt:' + bigInt.toString()); 115 116``` 117 118**`boolean` type** 119 120The `boolean` type represents logical values that are either `true` or `false`. 121 122Usually variables of this type are used in conditional statements: 123 124```typescript 125let isDone: boolean = false; 126 127// ... 128 129if (isDone) { 130 console.info('Done!'); 131} 132``` 133 134**`string` type** 135 136A `string` is a sequence of characters; some characters can be set by using escape sequences. 137 138A `string` literal consists of zero or more characters enclosed in single (') or double quotes ("). The special form of a string literal is the template literal enclosed in backticks (\`). 139 140```typescript 141let s1 = 'Hello, world!\n'; 142let s2 = "this is a string"; 143let a = 'Success'; 144let s3 = `The result is ${a}`; 145``` 146 147**`void` type** 148 149The `void` type is used to specify that a function does not return a value. 150This type has the only one value which is also `void`. As `void` is a reference type, it can be used as type argument for generic types. 151 152```typescript 153class Class<T> { 154 //... 155} 156let instance: Class <void> 157``` 158 159**`Object` type** 160 161An `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. 162```typescript 163let o1: Object = 'Alice'; 164let o2: Object = ['a','b']; 165let o3: Object = 1; 166``` 167 168**`array` type** 169 170An `array` is an object comprised of elements of data types assignable to the element type specified in the array declaration. 171A value of an array is set by using array composite literal, which 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. 172 173The following example creates the array with three elements: 174 175```typescript 176let names: string[] = ['Alice', 'Bob', 'Carol']; 177``` 178 179**`enum` type** 180 181An `enum` type is a value type with a defined set of named values called enum constants. 182In order to be used, an enum constant must be prefixed with an enum type name. 183 184```typescript 185enum ColorSet { Red, Green, Blue } 186let c: ColorSet = ColorSet.Red; 187``` 188 189A constant expression can be used to explicitly set the value of an enum constant. 190 191```typescript 192enum ColorSet { White = 0xFF, Grey = 0x7F, Black = 0x00 } 193let c: ColorSet = ColorSet.Black; 194``` 195 196**`Union` type** 197 198A `Union` type is a reference type which is created as a combination of multiple types. Values of union types can be valid values of all types a union was created from. 199 200```typescript 201class Cat { 202 name: string = 'cat'; 203 // ... 204} 205class Dog { 206 name: string = 'dog'; 207 // ... 208} 209class Frog { 210 name: string = 'frog'; 211 // ... 212} 213type Animal = Cat | Dog | Frog | number | string | null | undefined; 214// Cat, Dog, and Frog are some types (classes or interfaces). 215 216let animal: Animal = new Cat(); 217animal = new Frog(); 218animal = 42; 219animal = 'dog'; 220animal = undefined; 221// One may assign the variable of the union type with any valid value. 222``` 223 224There are different mechanisms to get a value of a particular type from a union. 225 226Example: 227 228```typescript 229class Cat { sleep () {}; meow () {} } 230class Dog { sleep () {}; bark () {} } 231class Frog { sleep () {}; leap () {} } 232 233type Animal = Cat | Dog | Frog; 234 235function foo(animal: Animal) { 236 if (animal instanceof Frog) { 237 animal.leap(); // animal is of type Frog here. 238 } 239 animal.sleep(); // Any animal can sleep. 240} 241``` 242 243**`Aliases` type** 244 245Type `Aliases` provides names for anonymous types (such as array, function, object literal or union type) or alternative names for existing types. 246 247```typescript 248type Matrix = number[][]; 249type Handler = (s: string, no: number) => string; 250type Predicate <T> = (x: T) => boolean; 251type NullableObject = Object | null; 252``` 253 254### Operators 255 256Assignment operators 257 258Simple assignment operator `=` is used as in `x = y`. 259 260Compound assignment operators combine an assignment with an operator. For example, `a += b` equals `a = a + b`, 261 262where `+=` is a compound assignment operator. 263 264Compound assignment operators are as follows: `+=`, `-=`, `*=`, `/=`, `%=`, `<<=`, `>>=`, `>>>=`, `&=`, `|=`, and `^=`. 265 266**Comparison operators** 267 268| Operator| Description | 269| -------- | ------------------------------------------------------------ | 270| `===` | Returns **true** if both operands are strict equal. (Operands of different types, such as string and number, are considered unequal.)| 271| `!==` | Returns **true** if both operands are not strict equal. (Operands of different types, such as string and number, are considered unequal.)| 272| `==` | Returns **true** if both operands are equal.| 273| `!=` | Returns **true** if both operands are not equal. | 274| `>` | Returns **true** if the left operand is greater than the right.| 275| `>=` | Returns **true** if the left operand is greater than or equal to the right.| 276| `<` | Returns **true** if the left operand is less than the right. | 277| `<=` | Returns **true** if the left operand is less than or equal to the right.| 278 279The differences between `===` and `==` are as follows: 280```typescript 281 let a:Object=1; 282 let b:Object='1'; 283 // == compares only the values. 284 console.info(a == b); // true 285 // === compares the values and types. 286 console.info(a === b); // false 287``` 288 289 290**Arithmetic operators** 291 292Unary operators are as follows: `-`, `+`, `--`, and `++`. 293 294Binary operators are as follows: 295 296| Operator| Description | 297| -------- | ------------------------ | 298| `+` | Addition | 299| `-` | Subtraction | 300| `*` | Multiplication | 301| `/` | Division | 302| `%` | Remainder after division| 303 304**Bitwise operators** 305 306| Operator| Description | 307| --------- | ------------------------------------------------------------ | 308| `a & b` | Bitwise AND: sets each bit to 1 if the corresponding bits of both operands are 1, otherwise to 0.| 309| `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.| 310| `a ^ b` | Bitwise XOR: sets each bit to 1 if the corresponding bits of both operands are different, otherwise to 0.| 311| `~ a` | Bitwise NOT: inverts the bits of the operand. | 312| `a << b` | Shift left: shifts the binary representation of *a* to the left by *b* bits.| 313| `a >> b` | Arithmetic right shift: shifts the binary representation of *a* to the right by *b* bits with sign-extension.| 314| `a >>> b` | Logical right shift: shifts the binary representation of *a* to the right by *b* bits with zero-extension.| 315 316**Logical operators** 317 318| Operator | Description| 319| ---------- | ----------- | 320| `a && b` | Logical AND| 321| `a || b` | Logical OR| 322| `! a` | Logical NOT| 323 324### Statements 325 326**`If` statement** 327 328An `if` statement is used to execute a sequence of statements when a logical condition is true, or another set of statements (if provided) otherwise. 329The `else` part can also contain more `if` statements. 330 331An `if` statement is as follows: 332 333```typescript 334if (condition1) { 335 // Statement 1 336} else if (condition2) { 337 // Statement 2 338} else { 339 // The else statement 340} 341``` 342 343All conditional expressions must be of any type. For types other than `boolean`, implicit conversion rules are applied: 344 345```typescript 346let s1 = 'Hello'; 347if (s1) { 348 console.info(s1); // Print "Hello" 349} 350 351let s2 = 'World'; 352if (s2.length != 0) { 353 console.info(s2); // Print "World" 354} 355``` 356 357**`Switch` statement** 358 359A `switch` statement is used to execute a sequence of statements that match the value of a `switch` expression. 360 361The **switch** statement is as follows: 362 363```typescript 364switch (expression) { 365 case label1: // Execute if label1 is matched. 366 // ... 367 // Statement 1 368 // ... 369 break; // Can be omitted. 370 case label2: 371 case label3: // Execute if label2 or label3 is matched. 372 // ... 373 // Statement 23 374 // ... 375 break; // Can be omitted. 376 default: 377 // Default statement 378} 379``` 380 381If the value of a `switch` expression equals the value of some label, then the corresponding statements are executed. 382 383If there is no match, and the `switch` has the `default` clause, then the `default` statements are executed. 384 385An optional `break` statement allows you to break out of the `switch` and continue executing the statement that follows the `switch`. 386 387If there is no `break`, then the next statements in the `switch` are executed. 388 389**Conditional expressions** 390 391A conditional expression returns the result of one of the other two expressions based on the Boolean value of the first expression. 392 393A conditional expression looks as follows: 394 395```typescript 396condition ? expression1 : expression2 397``` 398 399If the value of `condition` is truthy (a value that is considered `true`), the `expression1` is used as the result of the expression; otherwise, the `expression2` is used. 400 401Example: 402 403```typescript 404let message = Math.random() > 0.5 ? 'Valid' : 'Failed'; 405``` 406 407If the value of `condition` is not a Boolean value, implicit conversion is performed. 408 409Example: 410 411```typescript 412 console.info('a' ? 'true' : 'false'); // true 413 console.info('' ? 'true' : 'false'); // false 414 console.info(1 ? 'true' : 'false'); // true 415 console.info(0 ? 'true' : 'false'); // false 416 console.info(null ? 'true' : 'false'); // false 417 console.info(undefined ? 'true' : 'false'); // false 418``` 419 420**`For` statement** 421 422The `for` statement is executed repeatedly until the specified loop exit condition result is `false`. 423 424The `for` statement is as follows: 425 426```typescript 427for ([init]; [condition]; [update]) { 428 statements 429} 430``` 431 432When a `for` statement is executed, the following process takes place: 433 4341. An `init` expression is executed, if any. This expression usually initializes one or more loop counters. 4352. The `condition` is evaluated. If the value of `condition` is truthy (a value that is considered `true`), or if the conditional expression is omitted, the statements in the `for` body are to be executed. If the value of `condition` is falsy (a value that is considered `false`), the `for` loop terminates. 4363. The statements of the `for` body are executed. 4374. If there is an `update` expression, then the `update` expression is executed. 4385. Go back to step 2. 439 440Example: 441 442```typescript 443let sum = 0; 444for (let i = 0; i < 10; i += 2) { 445 sum += i; 446} 447``` 448 449**`For-of` statement** 450 451You can use the `for-of` statement to iterate over iterable types such as array, Set, Map, and string. A `for-of` statement looks as follows: 452 453```typescript 454for (forVar of IterableExpression) { 455 // process forVar 456} 457``` 458 459Example: 460 461```typescript 462for (let ch of 'a string object') { 463 console.info(ch); 464} 465``` 466 467**`While` statement** 468 469The `while` statement executes `statements` as long as the value of `condition` is `true`. A `while` statement looks as follows: 470 471```typescript 472while (condition) { 473 statements 474} 475``` 476 477Example: 478 479```typescript 480let n = 0; 481let x = 0; 482while (n < 3) { 483 n++; 484 x += n; 485} 486``` 487 488**`Do-while` statement** 489 490If the value of `condition` is truthy (a value that is considered `true`), the `statements` is executed repeatedly. A `do-while` statement looks as follows: 491 492```typescript 493do { 494 statements 495} while (condition) 496``` 497 498Example: 499 500```typescript 501let i = 0; 502do { 503 i += 1; 504} while (i < 10) 505``` 506 507**`Break` statement** 508 509A `break` statement is used to terminate any `loop` statement or `switch`. 510 511A `break` statement looks as follows: 512 513```typescript 514let x = 0; 515while (true) { 516 x++; 517 if (x > 5) { 518 break; 519 } 520} 521``` 522 523A `break` statement with a label identifier transfers control out of the enclosing statement to the one which has the same label identifier. 524 525Example: 526 527```typescript 528let x = 1; 529label: while (true) { 530 switch (x) { 531 case 1: 532 // statements 533 break label; // Break the while statement. 534 } 535} 536``` 537 538**`Continue` statement** 539 540A `continue` statement stops the execution of the current loop iteration and passes control to the next iteration. 541 542Example: 543 544```typescript 545let sum = 0; 546for (let x = 0; x < 100; x++) { 547 if (x % 2 == 0) { 548 continue; 549 } 550 sum += x; 551} 552``` 553 554**`Throw` and `Try` statements** 555 556A `throw` statement is used to throw an exception or an error: 557 558```typescript 559throw new Error('this error') 560``` 561 562A `try` statement is used to catch and handle an exception or an error: 563 564```typescript 565try { 566 // Statement block where an exception may occur 567} catch (e) { 568 // Handle the exception. 569} 570``` 571 572The example below shows the `throw` and `try` statements used to handle the zero division case: 573 574```typescript 575class ZeroDivisor extends Error {} 576 577function divide (a: number, b: number): number{ 578 if (b == 0) throw new ZeroDivisor(); 579 return a / b; 580} 581 582function process (a: number, b: number) { 583 try { 584 let res = divide(a, b); 585 console.info('result: ' + res); 586 } catch (x) { 587 console.error('some error'); 588 } 589} 590``` 591 592`finally` clause is also supported: 593 594```typescript 595function processData(s: string) { 596 let error: Error | null = null; 597 598 try { 599 console.info('Data processed: ' + s); 600 // ... 601 // Statement where an exception may occur 602 // ... 603 } catch (e) { 604 error = e as Error; 605 // ... 606 // Handle the exception. 607 // ... 608 } finally { 609 // Code that is executed regardless of whether an exception occurs 610 if (error != null) { 611 console.error(`Error caught: input='${s}', message='${error.message}'`); 612 } 613 } 614} 615``` 616 617## Function 618 619### Function Declaration 620 621A function declaration introduces a named function, specifying its name, parameters, return type and body. 622 623Below is a simple function with two string parameters and string return type: 624 6251. Parameter type annotation: **x: string, y: string** explicitly specifies the parameter type as string. 626 6272. Return value type: **: string** specifies the return value type of the function as string. 628 629```typescript 630function add(x: string, y: string): string { 631 let z: string = `${x} ${y}`; 632 return z; 633} 634``` 635 636For every parameter, its type annotation must be specified. An optional parameter allows you to omit this parameter when calling a function. The last parameter of a function can be a rest parameter. 637 638### Optional Parameter 639 640The format of the optional parameter can be `name?: Type`. 641 642```typescript 643function hello(name?: string) { 644 if (name == undefined) { 645 console.info('Hello!'); 646 } else { 647 console.info(`Hello, ${name}!`); 648 } 649} 650``` 651 652Another form contains an expression that specifies a default value. If the optional parameter is omitted in a function call, the default value of the parameter is used as the argument. 653 654```typescript 655function multiply(n: number, coeff: number = 2): number { 656 return n * coeff; 657} 658multiply(2); // Return 2*2. 659multiply(2, 3); // Return 2*3. 660``` 661 662### Rest Parameter 663 664The last parameter of a function can be a rest parameter in the format of `...restArgs`. It allows functions to take unlimited number of arguments of any specified type. 665 666```typescript 667function sum(...numbers: number[]): number { 668 let res = 0; 669 for (let n of numbers) 670 res += n; 671 return res; 672} 673 674sum(); // Return 0. 675sum(1, 2, 3); // Return 6. 676``` 677 678### Return Type 679 680If function return type can be inferred from its body content, then it can be omitted from the function declaration. 681 682```typescript 683// Explicit return type 684function foo(): string { return 'foo'; } 685 686// Implicit return type inferred as string 687function goo() { return 'goo'; } 688``` 689 690The 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. 691 692Both notations below are valid: 693 694```typescript 695function hi1() { console.info('hi'); } 696function hi2(): void { console.info('hi'); } 697``` 698 699### Function Scope 700 701Variables and other entities defined in a function are local to the function and cannot be accessed from the outside. 702 703If 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. 704 705```typescript 706let outerVar = 'I am outer '; 707 708function func() { 709 let outerVar = 'I am inside'; 710 console.info(outerVar); // Output: I am inside 711} 712 713func(); 714``` 715 716### Function Call 717 718Calling a function actually leads to the execution of its body, while the arguments of the call are assigned to the function parameters. 719 720If the function is defined as follows: 721 722```typescript 723function join(x: string, y: string): string { 724 let z: string = `${x} ${y}`; 725 return z; 726} 727``` 728 729Then this function is called with two parameters of the type `string`: 730 731```typescript 732let x = join('hello', 'world'); 733console.info(x); // Output: hello world 734``` 735 736### Function Type 737 738A Function type is commonly used as follows to define a callback: 739 740```typescript 741type trigFunc = (x: number) => number // This is a function type. 742 743function do_action(f: trigFunc) { 744 f(3.141592653589); // Call the function. 745} 746 747do_action(Math.sin); // Pass in the function as a parameter. 748``` 749 750### Arrow Function (Lambda Function) 751 752A function can be defined as an arrow function. Example: 753 754```typescript 755let sum = (x: number, y: number): number => { 756 return x + y; 757} 758``` 759 760An arrow function return type can be omitted; in such case, it is inferred from the function body. 761 762An expression can be specified as an arrow function to make the notation shorter, that is, the following two notations are equivalent: 763 764```typescript 765let sum1 = (x: number, y: number) => { return x + y; } 766let sum2 = (x: number, y: number) => x + y 767``` 768 769### Closure 770 771A 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. 772 773In the following example, the `f` function returns a closure that captures the `count` variable. Each time `z` is called, the value of `count` is retained and incremented. 774 775```typescript 776function f(): () => number { 777 let count = 0; 778 let g = (): number => { count++; return count; }; 779 return g; 780} 781 782let z = f(); 783z(); // Return 1. 784z(); // Return 2. 785``` 786 787### Function Overload Signature 788 789A 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 to the same function and immediately followed by the single implementation function. 790 791```typescript 792function foo(x: number): void; /* First function definition */ 793function foo(x: string): void; /* Second function definition */ 794function foo(x: number | string): void { /* Implementation signature */ 795} 796 797foo(123); // Use the first function definition. 798foo('aa'); // Use the second function definition. 799``` 800 801An error occurs if two overload signatures have identical names and parameter lists. 802 803## Class 804 805A class declaration introduces a new type and defines its fields, methods and constructors. 806 807In the following example, class `Person` is defined, which has fields **name** and **surname**, constructor, and the `fullName` method: 808 809```typescript 810class Person { 811 name: string = ''; 812 surname: string = ''; 813 constructor (n: string, sn: string) { 814 this.name = n; 815 this.surname = sn; 816 } 817 fullName(): string { 818 return this.name + ' ' + this.surname; 819 } 820} 821``` 822 823After the class is defined, its instances can be created by using the keyword `new`: 824 825```typescript 826let p = new Person('John', 'Smith'); 827console.info(p.fullName()); 828``` 829 830Alternatively, an instance can be created by using object literals: 831 832```typescript 833class Point { 834 x: number = 0; 835 y: number = 0; 836} 837let p: Point = {x: 42, y: 42}; 838``` 839 840### Field 841 842A field is a variable of some type that is declared directly in a class. 843 844Classes may have instance fields or static fields. 845 846**Instance fields** 847 848Instance fields exist on every instance of a class. Each instance has its own set of instance fields. 849 850An instance of the class is used to access an instance field. 851 852```typescript 853class Person { 854 name: string = ''; 855 age: number = 0; 856 constructor(n: string, a: number) { 857 this.name = n; 858 this.age = a; 859 } 860 861 getName(): string { 862 return this.name; 863 } 864} 865 866let p1 = new Person('Alice', 25); 867p1.name; // Alice 868let p2 = new Person('Bob', 28); 869p2.getName(); // Bob 870``` 871 872**Static fields** 873 874The 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. 875 876The class name is used to access a static field: 877 878```typescript 879class Person { 880 static numberOfPersons = 0; 881 constructor() { 882 // ... 883 Person.numberOfPersons++; 884 // ... 885 } 886} 887 888Person.numberOfPersons; 889``` 890 891**Field initializers** 892 893ArkTS requires that all fields are explicitly initialized with some values either when the field is declared or in the `constructor`. 894This 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. 895 896The following code (invalid in ArkTS) is error-prone: 897 898```typescript 899class Person { 900 name: string; // undefined 901 902 setName(n:string): void { 903 this.name = n; 904 } 905 906 getName(): string { 907 // Return type "string" hides the fact that name can be undefined. 908 // The most correct action would be to write the return type as "string | undefined". By doing so, we could tell the users of our API about all possible return values. 909 return this.name; 910 } 911} 912 913let jack = new Person(); 914// Assume that name is not assigned with a value, that is, jack.setName('Jack') is not called. 915jack.getName().length; // Runtime exception: name is undefined. 916``` 917 918In ArkTS, you should write code as follows: 919 920```typescript 921class Person { 922 name: string = ''; 923 924 setName(n:string): void { 925 this.name = n; 926 } 927 928 // The type is string in all cases, null and undefined are impossible. 929 getName(): string { 930 return this.name; 931 } 932} 933 934 935let jack = new Person(); 936// Assume that name is not assigned with a value, that is, jack.setName('Jack') is not called. 937jack.getName().length; // 0, no runtime error. 938``` 939 940The following shows how our code behaves if the field `name` can be `undefined`: 941 942```typescript 943class Person { 944 name?: string; // The field may be undefined. 945 946 setName(n:string): void { 947 this.name = n; 948 } 949 950 // Compilation error: name can be undefined. Therefore, the return value type of the API cannot be defined as string only. 951 getNameWrong(): string { 952 return this.name; 953 } 954 955 getName(): string | undefined { // Return type matches the type of name. 956 return this.name; 957 } 958} 959 960let jack = new Person(); 961// Assume that name is not assigned with a value, that is, jack.setName('Jack') is not called. 962 963// Compile-time error: Compiler suspects that the next line of code possibly accesses something undefined. 964jack.getName().length; // Compilation failed. 965 966jack.getName()?.length; // Successful compilation and no runtime error. 967``` 968 969**getter and setter** 970 971**setter** and **getter** can be used to provide controlled access to object properties. 972 973In the following example, a **setter** is used to forbid setting invalid values of the `_age` property: 974 975```typescript 976class Person { 977 name: string = ''; 978 private _age: number = 0; 979 get age(): number { return this._age; } 980 set age(x: number) { 981 if (x < 0) { 982 throw Error('Invalid age argument'); 983 } 984 this._age = x; 985 } 986} 987 988let p = new Person(); 989p.age; // Output 0. 990p.age = -42; // Error will be thrown as an attempt to set incorrect age. 991``` 992 993A class can define a **getter** or a **setter**. 994 995### Method 996 997A method is a function that belongs to a class. A class can define instance methods, static methods or both. A static method belongs to the class itself, and can have access to static fields only. A `while` instance method has access to both static (class) fields and instance fields including private ones of its class. 998 999**Instance method** 1000 1001The example below illustrates how instance methods work. 1002 1003The `calculateArea` method calculates the area of a rectangle by multiplying the height by the width: 1004 1005```typescript 1006class RectangleSize { 1007 private height: number = 0; 1008 private width: number = 0; 1009 constructor(height: number, width: number) { 1010 this.height = height; 1011 this.width = width; 1012 } 1013 calculateArea(): number { 1014 return this.height * this.width; 1015 } 1016} 1017``` 1018 1019To use an instance method, it must be called on an instance of the class: 1020 1021```typescript 1022let square = new RectangleSize(10, 10); 1023square.calculateArea(); // Output: 100 1024``` 1025 1026**Static method** 1027 1028The keyword `static` is used to declare a method as static. A static method belongs to the class itself and have access to static fields only. 1029 1030A static method defines a common behavior of the class as a whole. 1031 1032The class name is used to call a static method. 1033 1034```typescript 1035class Cl { 1036 static staticMethod(): string { 1037 return 'this is a static method.'; 1038 } 1039} 1040console.info(Cl.staticMethod()); 1041``` 1042 1043**Inheritance** 1044 1045A class can extend another class (called base class) and implement multiple APIs using the following syntax: 1046 1047```typescript 1048class [extends BaseClassName] [implements listOfInterfaces] { 1049 // ... 1050} 1051``` 1052 1053An inheritance class extends the fields and methods of the base class, but does not extend the constructor. An inheritance class allows you to define new fields and methods or override the methods defined by the base class. 1054 1055The class that is being extended by another class is called 'base class', 'parent class', or 'superclass'. The class that extends another class is called 'extended class', 'derived class', or 'child class'. 1056 1057Example: 1058 1059```typescript 1060class Person { 1061 name: string = ''; 1062 private _age = 0; 1063 get age(): number { 1064 return this._age; 1065 } 1066} 1067class Employee extends Person { 1068 salary: number = 0; 1069 calculateTaxes(): number { 1070 return this.salary * 0.42; 1071 } 1072} 1073``` 1074 1075A class containing the `implements` clause must implement all methods defined in all listed APIs, except the methods defined with default implementation. 1076 1077```typescript 1078interface DateInterface { 1079 now(): string; 1080} 1081class MyDate implements DateInterface { 1082 now(): string { 1083 // Here is the implementation. 1084 return 'now'; 1085 } 1086} 1087``` 1088 1089**Access to super** 1090 1091The keyword `super` can be used to access instance fields, instance methods and constructors from the super class. It is often used to extend basic functionality of child class with the required behavior taken from the super class: 1092 1093```typescript 1094class RectangleSize { 1095 protected height: number = 0; 1096 protected width: number = 0; 1097 1098 constructor (h: number, w: number) { 1099 this.height = h; 1100 this.width = w; 1101 } 1102 1103 draw() { 1104 /* Draw bounds. */ 1105 } 1106} 1107class FilledRectangle extends RectangleSize { 1108 color = '' 1109 constructor (h: number, w: number, c: string) { 1110 super(h, w); // Call of the super constructor. 1111 this.color = c; 1112 } 1113 1114 draw() { 1115 super.draw(); // Call of the super method. 1116 // super.height can be used here. 1117 /* Fill the rectangle. */ 1118 } 1119} 1120``` 1121 1122**Method overriding** 1123 1124A child class can override implementation of a method defined in its superclass. An overridden method must have the same types of parameters, and same or derived return type as the original method. 1125 1126```typescript 1127class RectangleSize { 1128 // ... 1129 area(): number { 1130 // Implementation 1131 return 0; 1132 } 1133} 1134class Square extends RectangleSize { 1135 private side: number = 0; 1136 area(): number { 1137 return this.side * this.side; 1138 } 1139} 1140``` 1141 1142**Method overload signature** 1143 1144A method can be specified to be called in different ways by writing overload signatures. To do so, several methods' headers that have the same name but different signatures are written to the same method and immediately followed by the single implementation method. 1145 1146```typescript 1147class C { 1148 foo(x: number): void; /* First signature */ 1149 foo(x: string): void; /* Second signature */ 1150 foo(x: number | string): void { /* Implementation signature */ 1151 } 1152} 1153let c = new C(); 1154c.foo(123); // Use the first signature. 1155c.foo('aa'); // Use the second signature. 1156``` 1157 1158An error occurs if two overload signatures have identical names and parameter lists. 1159 1160### Constructor 1161 1162A class declaration may contain a constructor that is used to initialize object state. 1163 1164A constructor is defined as follows: 1165 1166```typescript 1167constructor ([parameters]) { 1168 // ... 1169} 1170``` 1171 1172If no constructor is defined, then a default constructor with an empty parameter list is created automatically. Example: 1173 1174```typescript 1175class Point { 1176 x: number = 0; 1177 y: number = 0; 1178} 1179let p = new Point(); 1180``` 1181 1182In this case, the default constructor fills the instance fields with default values for the field types. 1183 1184**Constructor in a derived class** 1185 1186The first statement of a constructor body can use the keyword `super` to explicitly call a constructor of the direct superclass. 1187 1188```typescript 1189class RectangleSize { 1190 constructor(width: number, height: number) { 1191 // ... 1192 } 1193} 1194class Square extends RectangleSize { 1195 constructor(side: number) { 1196 super(side, side); 1197 } 1198} 1199``` 1200 1201**Constructor overload signature** 1202 1203A constructor can be specified to be called in different ways by writing overload signatures. To do so, several constructors' headers that have the same name but different signatures are written to the same constructor and immediately followed by the single implementation constructor. 1204 1205```typescript 1206class C { 1207 constructor(x: number) /* First signature */ 1208 constructor(x: string) /* Second signature */ 1209 constructor(x: number | string) { /* Implementation signature */ 1210 } 1211} 1212let c1 = new C(123); // Use the first signature. 1213let c2 = new C('abc'); // Use the second signature. 1214``` 1215 1216An error occurs if two overload signatures have identical names and parameter lists. 1217 1218### Visibility Modifiers 1219 1220Both methods and properties of a class can have visibility modifiers. 1221 1222Visibility modifiers include `private`, `protected`, and `public`. The default visibility is `public`. 1223 1224**Public** 1225 1226The `public` members (fields, methods, constructors) of a class are visible in any part of the program, where their class is visible. 1227 1228**Private** 1229 1230A `private` member cannot be accessed outside the class where it is declared in. Example: 1231 1232```typescript 1233class C { 1234 public x: string = ''; 1235 private y: string = ''; 1236 set_y (new_y: string) { 1237 this.y = new_y; // OK, as y is accessible within the class itself. 1238 } 1239} 1240let c = new C(); 1241c.x = 'a'; // OK, as the field is public. 1242c.y = 'b'; // Compile-time error: 'y' is not visible. 1243``` 1244 1245**Protected** 1246 1247The modifier `protected` acts much like the modifier `private`, but the `protected` members are also accessible in derived classes. Example: 1248 1249```typescript 1250class Base { 1251 protected x: string = ''; 1252 private y: string = ''; 1253} 1254class Derived extends Base { 1255 foo() { 1256 this.x = 'a'; // Access the protected member. 1257 this.y = 'b'; // Compile-time error: 'y' is not visible, because it is private. 1258 } 1259} 1260``` 1261 1262### Object Literal 1263 1264An 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. 1265 1266An object literal is a list of ***property name*: *value*** enclosed in a pair of curly brackets ({}). 1267 1268```typescript 1269class C { 1270 n: number = 0; 1271 s: string = ''; 1272} 1273 1274let c: C = {n: 42, s: 'foo'}; 1275``` 1276 1277ArkTS is a statically typed language. As shown in the preceding example, object literals can be used only in contexts where the literal type can be inferred. Other valid cases are illustrated below: 1278 1279```typescript 1280class C { 1281 n: number = 0; 1282 s: string = ''; 1283} 1284 1285function foo(c: C) {} 1286 1287let c: C 1288 1289c = {n: 42, s: 'foo'}; // Use the variable type. 1290foo({n: 42, s: 'foo'}); // Use the parameter type. 1291 1292function bar(): C { 1293 return {n: 42, s: 'foo'}; // Use the return type. 1294} 1295``` 1296 1297You can also use the object literals in array element types or class field types. 1298 1299```typescript 1300class C { 1301 n: number = 0; 1302 s: string = ''; 1303} 1304let cc: C[] = [{n: 1, s: 'a'}, {n: 2, s: 'b'}]; 1305``` 1306 1307**Object literal of `Record` type** 1308 1309The generic `Record<K, V>` type is used to map the properties of a type (Key type) to another type (Value type). A special form of object literal is used to initialize the value of such type: 1310 1311```typescript 1312let map: Record<string, number> = { 1313 'John': 25, 1314 'Mary': 21, 1315} 1316 1317map['John']; // 25 1318``` 1319 1320The `K` type can be either string or number (excluding bigint), while `V` can be any type. 1321 1322```typescript 1323interface PersonInfo { 1324 age: number; 1325 salary: number; 1326} 1327let map: Record<string, PersonInfo> = { 1328 'John': { age: 25, salary: 10}, 1329 'Mary': { age: 21, salary: 20} 1330} 1331``` 1332 1333### Abstract Class 1334 1335A 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. 1336 1337A compile-time error occurs if an attempt is made to create an instance of an abstract class: 1338 1339```typescript 1340abstract class X { 1341 field: number; 1342 constructor(p: number) { 1343 this.field = p; 1344 } 1345} 1346 1347let x = new X(666) // Compile-time error: Cannot create an instance of an abstract class. 1348``` 1349 1350Child classes of an abstract class can be non-abstract or in turn abstract. A non-abstract child class of an abstract parent class can be instantiated. As a result, a constructor for the abstract class, and field initializers for non-static fields of that class are executed: 1351 1352```typescript 1353abstract class Base { 1354 field: number; 1355 constructor(p: number) { 1356 this.field = p; 1357 } 1358} 1359 1360class Derived extends Base { 1361 constructor(p: number) { 1362 super(p); 1363 } 1364} 1365 1366let x = new Derived(666); 1367``` 1368 1369**Abstract method** 1370 1371A method with the modifier `abstract` is considered an abstract method. Abstract methods do not have bodies, that is, they can be declared but not implemented. 1372 1373Only abstract classes can have abstract methods. A compile-time error occurs if a non-abstract class has an abstract method: 1374 1375```typescript 1376class Y { 1377 abstract method(p: string) // Compile-time error: Abstract methods can only appear within an abstract class. 1378} 1379``` 1380 1381## Interface 1382 1383An interface declaration introduces a new type. Interfaces are a common way of defining contracts between various part of codes. 1384 1385Interfaces are used to write polymorphic code, which can be applied to any class instances that implement a particular interface. 1386 1387An interface usually contains properties and method declarations. 1388 1389Example: 1390 1391```typescript 1392interface Style { 1393 color: string; // Property 1394} 1395interface AreaSize { 1396 calculateAreaSize(): number; // Method declaration 1397 someMethod(): void; // Method declaration 1398} 1399``` 1400 1401Example of a class implementing an interface: 1402 1403```typescript 1404// Interface: 1405interface AreaSize { 1406 calculateAreaSize(): number; // Method declaration 1407 someMethod(): void; // Method declaration 1408} 1409 1410// Implementation 1411class RectangleSize implements AreaSize { 1412 private width: number = 0; 1413 private height: number = 0; 1414 someMethod(): void { 1415 console.info('someMethod called'); 1416 } 1417 calculateAreaSize(): number { 1418 this.someMethod(); // Call another method and return the result. 1419 return this.width * this.height; 1420 } 1421} 1422``` 1423 1424### Interface Property 1425 1426An interface property can be in a form of field, **getter**, **setter**, or both **getter** and **setter**. 1427 1428A property field is just a shortcut notation of a **getter** or **setter** pair, and the following notations are equal: 1429 1430```typescript 1431interface Style { 1432 color: string; 1433} 1434``` 1435 1436```typescript 1437interface Style { 1438 get color(): string; 1439 set color(x: string); 1440} 1441``` 1442 1443A class that implements an interface may also use a short or a long notation: 1444 1445```typescript 1446interface Style { 1447 color: string; 1448} 1449 1450class StyledRectangle implements Style { 1451 color: string = ''; 1452} 1453``` 1454 1455```typescript 1456interface Style { 1457 color: string; 1458} 1459 1460class StyledRectangle implements Style { 1461 private _color: string = ''; 1462 get color(): string { return this._color; } 1463 set color(x: string) { this._color = x; } 1464} 1465``` 1466 1467### Interface Inheritance 1468 1469An interface may extend other interfaces, as shown in the example below: 1470 1471```typescript 1472interface Style { 1473 color: string; 1474} 1475 1476interface ExtendedStyle extends Style { 1477 width: number; 1478} 1479``` 1480 1481An extended interface contains all properties and methods of the interface it extends, and can also add its own properties and methods. 1482 1483 1484### Abstract Class and Interface 1485 1486Abstract classes and interfaces cannot be instantiated. Abstract classes are abstractions of classes, used to capture the general characteristics of child classes, and interfaces are abstractions of behavior. The differences between abstract classes and interfaces in ArkTS are as follows: 1487 1488* A class can extend only one abstract class, but can implement one or more interfaces. 1489```typescript 1490// The Bird class extends the abstract class Animal and implements multiple interfaces CanFly and CanSwim. 1491class Bird extends Animal implements CanFly, CanSwim { 1492 // ... 1493} 1494``` 1495* An abstract class, instead of an interface, can contain static code blocks or static methods. 1496```typescript 1497interface MyInterface { 1498 // Error: The interface cannot contain static members. 1499 static staticMethod(): void; 1500 1501 // Error: The interface cannot contain static code blocks. 1502 static { console.info("static") }; 1503} 1504 1505abstract class MyAbstractClass { 1506 // Correct: An abstract class can contain static methods. 1507 static staticMethod(): void { console.info("static");} 1508 1509 // Correct: An abstract class can contain static code blocks. 1510 static { console.info("static initialization block");} 1511} 1512``` 1513* In abstract classes, there can be implementations of methods, but interfaces are completely abstract and there is no implementation of methods. 1514```typescript 1515abstract class MyAbstractClass { 1516 // Correct: An abstract class can contain implementation of methods. 1517 func(): void { console.info("func");} 1518} 1519interface MyInterface { 1520 // Error: Interfaces are completely abstract and there is no implementation of methods. 1521 func(): void { console.info("func");} 1522} 1523``` 1524* Abstract classes can have constructors, while interfaces cannot. 1525```typescript 1526abstract class MyAbstractClass { 1527 constructor(){} // Correct: Abstract classes can have constructors. 1528} 1529interface MyInterface { 1530 constructor(); // Error: Interfaces cannot contain constructors. 1531} 1532``` 1533 1534## Generic Type and Function 1535 1536Generic type and function enable code to operate on multiple data types in a type-safe way without writing repetitive logic for each type. 1537 1538### Generic Class and Interface 1539 1540A class and an interface can be defined as generics. Add parameters to the type definition, such as the type parameter `Element` in the following example: 1541 1542```typescript 1543class CustomStack<Element> { 1544 public push(e: Element):void { 1545 // ... 1546 } 1547} 1548``` 1549 1550To use type **CustomStack**, the type argument must be specified for each type parameter: 1551 1552```typescript 1553let s = new CustomStack<string>(); 1554s.push('hello'); 1555``` 1556 1557Compiler ensures type safety while working with generic types and functions. Refer to the example below: 1558 1559```typescript 1560let s = new CustomStack<string>(); 1561s.push(55); // A compile-time error is thrown. 1562``` 1563 1564### Generic Constraints 1565 1566Type parameters of generic types can be bounded. For example, the `Key` type parameter in the `MyHashMap<Key, Value>` class must have the `hash` method. 1567 1568```typescript 1569interface Hashable { 1570 hash(): number; 1571} 1572class MyHashMap<Key extends Hashable, Value> { 1573 public set(k: Key, v: Value) { 1574 let h = k.hash(); 1575 // Other code is omitted here. 1576 } 1577} 1578``` 1579 1580In the above example, the `Key` type extends `Hashable`, and all methods of `Hashable` interface can be called for keys. 1581 1582### Generic Function 1583 1584Use a generic function to create a more universal code. Consider a function that returns the last element of the array: 1585 1586```typescript 1587function last(x: number[]): number { 1588 return x[x.length - 1]; 1589} 1590last([1, 2, 3]); // 3 1591``` 1592 1593If the same function needs to be defined for any array, then define it as a generic with a type parameter: 1594 1595```typescript 1596function last<T>(x: T[]): T { 1597 return x[x.length - 1]; 1598} 1599``` 1600 1601Now, the function can be used with any array. 1602 1603In a function call, type argument can be set explicitly or implicitly: 1604 1605```typescript 1606// Explicit type argument 1607let res: string = last<string>(['aa', 'bb']); 1608let res: number = last<number>([1, 2, 3]); 1609 1610// Implicit type argument 1611// Compiler determines the type argument based on the type of the call arguments. 1612let res: number = last([1, 2, 3]); 1613``` 1614 1615### Generic Default 1616 1617Type parameters of generic types can have defaults. It allows using just the generic type name instead of specifying the actual type arguments. The example below illustrates this feature of both class and function. 1618 1619```typescript 1620class SomeType {} 1621interface Interface <T1 = SomeType> { } 1622class Base <T2 = SomeType> { } 1623class Derived1 extends Base implements Interface { } 1624// Derived1 is semantically equivalent to Derived2. 1625class Derived2 extends Base<SomeType> implements Interface<SomeType> { } 1626 1627function foo<T = number>(): T { 1628 // ... 1629} 1630foo(); 1631// Such function is semantically equivalent to the call below: 1632foo<number>(); 1633``` 1634 1635## Null Safety 1636 1637All types in ArkTS by default are non-nullable, so the value of a type cannot be null. It is similar to TypeScript behavior in strict null checking mode (`strictNullChecks`), but the rules in ArkTS are stricter. 1638 1639In the following example, all lines lead to a compile-time error: 1640 1641```typescript 1642let x: number = null; // Compile-time error 1643let y: string = null; // Compile-time error 1644let z: number[] = null; // Compile-time error 1645``` 1646 1647A variable that can have a null value is defined with a union type `T | null`. 1648 1649```typescript 1650let x: number | null = null; 1651x = 1; // ok 1652x = null; // ok 1653if (x != null) { /* do something */ } 1654``` 1655 1656### Non-Null Assertion Operator 1657 1658A postfix operator `!` can be used to assert that its operand is non-null. 1659 1660When applied to a value of a nullable type, the type becomes non-nullable at compile time. For example, the type of the value is changed from `T | null` to `T`: 1661 1662```typescript 1663class A { 1664 value: number = 0; 1665} 1666 1667function foo(a: A | null) { 1668 a.value; // Compile-time error: cannot access to a nullable value. 1669 a!.value; // If the value of a is not null at runtime, the fields of a can be accessed; if the value of a is null at runtime, a runtime exception occurs. 1670} 1671``` 1672 1673### Null-Coalescing Operator 1674 1675The null-coalescing binary operator `??` checks whether the evaluation of the left-hand-side expression is equal to `null` or `undefined`. If it is, the result of the expression is the right-hand-side expression; otherwise, it is the left-hand-side expression. 1676 1677In other words, `a ?? b` equals the ternary operator `(a != null && a != undefined) ? a : b`. 1678 1679In the following example, the `getNick` method returns a nickname if it is set; otherwise, an empty string is returned: 1680 1681```typescript 1682class Person { 1683 // ... 1684 nick: string | null = null; 1685 getNick(): string { 1686 return this.nick ?? ''; 1687 } 1688} 1689``` 1690 1691### Optional Chaining 1692 1693If the object property is `undefined` or `null` when it is being accessed, the optional chaining operator returns `undefined`. 1694 1695```typescript 1696class Person { 1697 nick: string | null = null; 1698 spouse?: Person 1699 1700 setSpouse(spouse: Person): void { 1701 this.spouse = spouse; 1702 } 1703 1704 getSpouseNick(): string | null | undefined { 1705 return this.spouse?.nick; 1706 } 1707 1708 constructor(nick: string) { 1709 this.nick = nick; 1710 this.spouse = undefined; 1711 } 1712} 1713``` 1714 1715Note: The return type of `getSpouseNick` must be `string | null | undefined`, as the method can return `null` or `undefined`. 1716 1717The optional chaining can be of any length and can contain any number of `?.` operators. 1718 1719In the following example, if the `spouse` property of the `Person` instance and the `nick` property of `spouse` both are not null, the `spouse.nick` is output. Otherwise, `undefined` is output. 1720 1721```typescript 1722class Person { 1723 nick: string | null = null; 1724 spouse?: Person; 1725 1726 constructor(nick: string) { 1727 this.nick = nick; 1728 this.spouse = undefined; 1729 } 1730} 1731 1732let p: Person = new Person('Alice'); 1733p.spouse?.nick; // undefined 1734``` 1735 1736## Module 1737 1738Programs are organized as sets of compilation units or modules. 1739 1740Each module creates its own scope, that is, any declarations (variables, functions, classes, etc.) declared in the module are not visible outside that module unless they are explicitly exported. 1741 1742Conversely, a variable, function, class, or interface exported from another module must first be imported to a module. 1743 1744### Export 1745 1746A top-level declaration can be exported by using the keyword `export`. 1747 1748A declared name that is not exported is considered private and can be used only in the module where it is declared. 1749 1750```typescript 1751export class Point { 1752 x: number = 0; 1753 y: number = 0; 1754 constructor(x: number, y: number) { 1755 this.x = x; 1756 this.y = y; 1757 } 1758} 1759export let Origin = new Point(0, 0); 1760export function Distance(p1: Point, p2: Point): number { 1761 return Math.sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)); 1762} 1763``` 1764**Exporting default objects** 1765```typescript 1766class Demo{ 1767 constructor(){ 1768 } 1769} 1770export default new Demo(); 1771 1772``` 1773 1774### Import 1775 1776**Static import** 1777 1778Import declarations are used to import entities exported from other modules and provide their bindings in the current module. An import declaration consists of two parts: 1779 1780* Import path that determines the module to import from. 1781* Import bindings that define the set of usable entities in the imported module, and the form of use (qualified or unqualified). 1782 1783Import bindings may have several forms. 1784 1785Let's assume a module has the path **./utils** and export entities **X** and **Y**. 1786 1787An 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`: 1788 1789```typescript 1790import * as Utils from './utils'; 1791Utils.X // Denote X from Utils. 1792Utils.Y // Denote Y from Utils. 1793``` 1794 1795An import binding of the form `{ ident1, ..., identN }` binds an exported entity with a specified name, which can be used as a simple name: 1796 1797```typescript 1798import { X, Y } from './utils'; 1799X // Denote X from utils. 1800Y // Denote Y from utils. 1801``` 1802 1803If a list of identifiers contains an alias in the form `ident as alias`, the entity `ident` is bound under the name `alias`: 1804 1805```typescript 1806import { X as Z, Y } from './utils'; 1807Z // Denote X from Utils. 1808Y // Denote Y from Utils. 1809X // Compile-time error: 'X' is not visible. 1810``` 1811 1812**Dynamic import** 1813Unlike static import, dynamic import allows you to load a module conditionally or on demand. 1814The **import()** syntax, commonly called dynamic import, is a function-like expression that allows for dynamic loading of a module. A promise is returned when this method is invoked. 1815In the following example, **import(modulePath)** loads a 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. 1816 1817```typescript 1818// Calc.ts 1819export function add(a:number, b:number):number { 1820 let c = a + b; 1821 console.info('Dynamic import, %d + %d = %d', a, b, c); 1822 return c; 1823} 1824 1825// Index.ts 1826import("./Calc").then((obj: ESObject) => { 1827 console.info(obj.add(3, 5)); 1828}).catch((err: Error) => { 1829 console.error("Module dynamic import error: ", err); 1830}); 1831``` 1832 1833You can also use **let module = await import(modulePath)** inside an async function. 1834 1835```typescript 1836// say.ts 1837export function hi() { 1838 console.info('Hello'); 1839} 1840export function bye() { 1841 console.info('Bye'); 1842} 1843``` 1844 1845Then dynamic import can be like this: 1846 1847```typescript 1848async function test() { 1849 let ns = await import('./say'); 1850 let hi = ns.hi; 1851 let bye = ns.bye; 1852 hi(); 1853 bye(); 1854} 1855``` 1856 1857For more details about dynamic import, see [Dynamic Import](../arkts-utils/arkts-dynamic-import.md). 1858 1859<!--RP2--><!--RP2End--> 1860 1861### Top-Level Statement 1862 1863Top-level statements are those written at the outermost layer of a module, not wrapped by any function, class, or block scope. These statements include variable declarations, function declarations, and expressions. 1864 1865## Keyword 1866 1867### this 1868 1869The keyword `this` can only be used in instance methods of a class. 1870 1871**Example** 1872 1873```typescript 1874class A { 1875 count: string = 'a'; 1876 m(i: string): void { 1877 this.count = i; 1878 } 1879} 1880``` 1881 1882Constraints: 1883 1884* Type notation using `this` is not supported. 1885* `this` is not allowed in functions and static methods of classes. 1886 1887**Example** 1888 1889```typescript 1890class A { 1891 n: number = 0; 1892 f1(arg1: this) {} // Compile-time error: Type notation using this is not supported. 1893 static f2(arg1: number) { 1894 this.n = arg1; // Compile-time error: `this` is not allowed in the static methods of classes. 1895 } 1896} 1897 1898function foo(arg1: number) { 1899 this.n = i; // Compile-time error: `this` is not allowed in functions. 1900} 1901``` 1902 1903The keyword `this` used as a primary expression denotes a value that is a reference to the following: 1904 1905* Object for which the instance method 1906* Object being constructed 1907 1908## Annotation 1909 1910Annotation is a language feature that changes the semantics of application declarations by adding metadata. 1911The declaration and usage of annotations are as follows: 1912 1913**Example** 1914 1915```typescript 1916// Declaration of an annotation: 1917@interface ClassAuthor { 1918 authorName: string 1919} 1920 1921// Usage of an annotation: 1922@ClassAuthor({authorName: "Bob"}) 1923class MyClass { 1924 // ... 1925} 1926``` 1927 1928- The `ClassAuthor` annotation should add metadata to the class declaration. 1929- The annotation must be placed before the declaration. 1930- The annotation can contain the parameters shown in the preceding example. 1931 1932The name of the annotation to be used must be prefixed with the `@` symbol (for example, **@MyAnno**). No space or line separator is allowed between the `@` symbol and the name. 1933```typescript 1934ClassAuthor({authorName: "Bob"}) // Compile-time error: The annotation must be prefixed with '@'. 1935@ ClassAuthor({authorName: "Bob"}) // Compile-time error: No space or line separator is allowed between the @ symbol and the name. 1936``` 1937If the annotation name cannot be accessed, a compile-time error occurs. 1938Annotation declarations can be exported and used in other files. 1939 1940Multiple annotations can be applied to the same declaration (the sequence of annotations does not affect the usage). 1941```typescript 1942@MyAnno() 1943@ClassAuthor({authorName: "John Smith"}) 1944class MyClass { 1945 // ... 1946} 1947``` 1948Annotations are not features in TypeScript and can be used only in `.ets` and `.d.ets` files. 1949 1950### Custom Annotation 1951 1952**Declaration of custom annotation** 1953The definition of custom annotation is similar to that of `interface`. The `interface` keyword is prefixed with the `@` symbol.<br> 1954The following types can be used for annotation fields: 1955* Number 1956* Boolean 1957* String 1958* Enum 1959* Array of the preceding types 1960>**NOTE** 1961> 1962> - If other types are used for annotation fields, a compile-time error occurs. 1963> - The bigint type is not supported for annotation field. 1964 1965The default value of an annotation field must be specified using a constant expression.<br>The following types of constant expressions are used: 1966* Numeric literal 1967* Boolean literal 1968* String literal 1969* Enum (values must be determined during compilation) 1970* Array of the preceding constants 1971>**NOTE** 1972> 1973> If the enums cannot be determined during compilation, a compile-time error is reported. 1974```typescript 1975// a.ts 1976export enum X { 1977 x = foo(); // x is not a constant that can be determined during compilation. 1978} 1979 1980// b.ets 1981import {X} from './a'; 1982 1983@interface Position { 1984 data: number = X.x; // Compile-time error: The default value of the annotation field must be a constant expression. 1985} 1986``` 1987Annotations must be defined in the top-level scope. Otherwise, a compile-time error is reported.<br> 1988The name of an annotation cannot be the same as that of another entity visible in the scope where the annotation is defined. Otherwise, a compile-time error is reported.<br> 1989Annotations do not support the merging feature in TypeScript. Otherwise, a compile-time error is reported. 1990```typescript 1991namespace ns { 1992 @interface MataInfo { // Compile-time error: Annotations must be defined in the top-level scope. 1993 // ... 1994 } 1995} 1996 1997@interface Position { 1998 // ... 1999} 2000 2001class Position { // Compile-time error: The name of an annotation cannot be the same as that of another entity visible in the scope where the annotation is defined. 2002 // ... 2003} 2004 2005@interface ClassAuthor { 2006 name: string; 2007} 2008 2009@interface ClassAuthor { // Compile-time error: The name of an annotation cannot be the same as that of another entity visible in the scope where the annotation is defined. 2010 data: sting; 2011} 2012``` 2013Annotations are not types. If annotations are used as types, a compile-time error is reported. For example, type aliases are used for annotations. 2014```typescript 2015@interface Position {} 2016type Pos = Position; // Compile-time error: Annotations are not types. 2017``` 2018Annotations cannot be added to the **getter** and **setter** methods of a class. Otherwise, a compile-time error is reported. 2019```typescript 2020@interface ClassAuthor { 2021 authorName: string; 2022} 2023 2024@ClassAuthor({authorName: "John Smith"}) 2025class MyClass { 2026 private _name: string = "Bob"; 2027 2028 @ClassAuthor({authorName: "John Smith"}) // Compile-time error: Annotations cannot be added to the getter and setter methods of a class. 2029 get name() { 2030 return this._name; 2031 } 2032 2033 @ClassAuthor({authorName: "John Smith"}) // Compile-time error: Annotations cannot be added to the getter and setter methods of a class. 2034 set name(authorName: string) { 2035 this._name = authorName; 2036 } 2037} 2038``` 2039 2040**Usage of custom annotation** 2041The following is an example of annotation declaration: 2042```typescript 2043@interface ClassPreamble { 2044 authorName: string; 2045 revision: number = 1; 2046} 2047@interface MyAnno {} 2048``` 2049Currently, annotations can be used only for class declarations and method declarations. The same annotation can be used for classes and methods.<br>The following is an example of annotation usage: 2050```typescript 2051@ClassPreamble({authorName: "John", revision: 2}) 2052class C1 { 2053 // ... 2054} 2055 2056@ClassPreamble({authorName: "Bob"}) // The default value of revision is 1. 2057class C2 { 2058 // ... 2059} 2060 2061@MyAnno() // The same annotation can be used for classes and methods. 2062class C3 { 2063 @MyAnno() 2064 foo() {} 2065 @MyAnno() 2066 static bar() {} 2067} 2068``` 2069The field sequence in an annotation does not affect the usage. 2070```typescript 2071@ClassPreamble({authorName: "John", revision: 2}) 2072// the same as: 2073@ClassPreamble({revision: 2, authorName: "John"}) 2074``` 2075When using an annotation, you must assign values to the fields that do not have default values. Otherwise, a compile-time error occurs. 2076>**NOTE** 2077> 2078> The value to assign must be of the same type as the annotation declaration and only constant expressions can be used. 2079```typescript 2080@ClassPreamble() // Compile-time error: The authorName field is not defined. 2081class C1 { 2082 // ... 2083} 2084``` 2085If a field of the array type is defined in an annotation, use an array literal to set the value of the field. 2086```typescript 2087@interface ClassPreamble { 2088 authorName: string; 2089 revision: number = 1; 2090 reviewers: string[]; 2091} 2092 2093@ClassPreamble( 2094 { 2095 authorName: "Alice", 2096 reviewers: ["Bob", "Clara"] 2097 } 2098) 2099class C3 { 2100 // ... 2101} 2102``` 2103If it is not necessary to define an annotation field, you can omit the parentheses following the annotation name. 2104```typescript 2105@MyAnno 2106class C4 { 2107 // ... 2108} 2109``` 2110 2111**Importing and exporting annotations** 2112Annotations can also be imported and exported. Currently, only the annotations in the `export @interface` form can be exported.<br> 2113**Example** 2114```typescript 2115export @interface MyAnno {} 2116``` 2117Currently, only the annotations in the `import {}` and `import * as` forms can be imported.<br> 2118**Example** 2119```typescript 2120// a.ets 2121export @interface MyAnno {} 2122export @interface ClassAuthor {} 2123 2124// b.ets 2125import { MyAnno } from './a'; 2126import * as ns from './a'; 2127 2128@MyAnno 2129@ns.ClassAuthor 2130class C { 2131 // ... 2132} 2133``` 2134- Annotation renaming is not allowed in **import**. 2135```typescript 2136import { MyAnno as Anno } from './a'; // Compile-time error: Annotation renaming is not allowed in import. 2137``` 2138Any other forms of **import** or **export** are not allowed for annotations. Otherwise, a compile-time error is reported. 2139- As annotations are not types, the `type` symbol is not allowed for import and export. 2140```typescript 2141import type { MyAnno } from './a'; // Compile-time error: The type symbol is not allowed for annotation import and export. 2142``` 2143 2144- If an annotation is imported only from a module, the module side effects will not be triggered. 2145```typescript 2146// a.ets 2147export @interface Anno {} 2148 2149export @interface ClassAuthor {} 2150 2151console.info("hello"); 2152 2153// b.ets 2154import { Anno } from './a'; 2155import * as ns from './a'; 2156 2157@MyAnno 2158@ns.ClassAuthor // Only the annotation of ns is referenced, which does not execute console.info of a.ets. 2159class X { 2160 // ... 2161} 2162``` 2163 2164**Annotations in .d.ets files** 2165Annotations can be used in .d.ets files. 2166You can declare annotations using ambient declarations in .d.ets files. 2167```typescript 2168ambientAnnotationDeclaration: 2169 'declare' userDefinedAnnotationDeclaration 2170 ; 2171``` 2172 2173**Example** 2174```typescript 2175// a.d.ets 2176export declare @interface ClassAuthor {} 2177``` 2178In the preceding declaration: 2179- No new annotation definition is introduced, but the annotation type information is provided. 2180- Annotations must be defined in other source code files. 2181- The ambient declaration and implementation of an annotation must be the same, including the field type and default value. 2182```typescript 2183// a.d.ets 2184export declare @interface NameAnno{name: string = ""} 2185 2186// a.ets 2187export @interface NameAnno{name: string = ""} // ok 2188``` 2189The ambient declaration of an annotation is similar to that of a class and can also be imported. 2190```typescript 2191// a.d.ets 2192export declare @interface MyAnno {} 2193 2194// b.ets 2195import { MyAnno } from './a'; 2196 2197@MyAnno 2198class C { 2199 // ... 2200} 2201``` 2202 2203**.d.ets files automatically generated by a compiler**<br> 2204When a compiler automatically generates .d.ets files based on ETS code, the following situations may occur: 22051. When the annotation definition is exported, the annotation definition in the source code is retained in the .d.ets file. 2206```typescript 2207// a.ets 2208export @interface ClassAuthor {} 2209 2210@interface MethodAnno { // Not exported 2211 data: number; 2212} 2213 2214// Declaration file generated by the a.d.ets compiler 2215export declare @interface ClassAuthor {} 2216``` 22172. If all the following conditions are met, the annotation instance of the entity in the source code is retained in the .d.ets file.<br> 2218 2.1 The annotation definition (including imported annotation) is exported.<br> 2219 2.2 If the entity is a class, the class is exported.<br> 2220 2.3 If the entity is a method, the class is exported, and the method is not private. 2221```typescript 2222// a.ets 2223import { ClassAuthor } from './author'; 2224 2225export @interface MethodAnno { 2226 data: number = 0; 2227} 2228 2229@ClassAuthor 2230class MyClass { 2231 @MethodAnno({data: 123}) 2232 foo() {} 2233 2234 @MethodAnno({data: 456}) 2235 private bar() {} 2236} 2237 2238// Declaration file generated by the a.d.ets compiler 2239import {ClassAuthor} from "./author"; 2240 2241export declare @interface MethodAnno { 2242 data: number = 0; 2243} 2244 2245@ClassAuthor 2246export declare class C { 2247 @MethodAnno({data: 123}) 2248 foo(): void; 2249 2250 bar; // Annotations are not retained for private methods. 2251} 2252``` 2253 2254**.d.ets file generated by the developer**<br> 2255The annotation information in the .d.ets file generated by you is not automatically applied to the implemented source code.<br> 2256**Example** 2257```typescript 2258// Declaration file generated by you in b.d.ets 2259@interface ClassAuthor {} 2260 2261@ClassAuthor // The declaration file contains annotations. 2262class C { 2263 // ... 2264} 2265 2266// Source code of the declaration file implemented by you in b.ets 2267@interface ClassAuthor {} 2268 2269// The implementation file does not contain annotations. 2270class C { 2271 // ... 2272} 2273``` 2274In the final build product, **class C** does not have annotations. 2275 2276**Duplicate annotations and inheritance** 2277The same annotation cannot be used repeatedly for the same entity. Otherwise, a compile-time error occurs. 2278```typescript 2279@MyAnno({name: "123", value: 456}) 2280@MyAnno({name: "321", value: 654}) // Compile-time error: Duplicate annotations are not allowed. 2281class C { 2282 // ... 2283} 2284``` 2285A child class does not extend the annotations of the base class or that of the methods of the base class. 2286 2287**Annotations, abstract classes, and abstract methods** 2288Annotations cannot be used for abstract classes or abstract methods. Otherwise, a compile-time error occurs. 2289```typescript 2290@MyAnno // Compile-time error: Annotations cannot be used for abstract classes and abstract methods. 2291abstract class C { 2292 @MyAnno 2293 abstract foo(): void; // Compile-time error: Annotations cannot be used for abstract classes and abstract methods. 2294} 2295``` 2296 2297## ArkUI Supports 2298 2299This section demonstrates the mechanism provided by ArkTS for creating GUIs. ArkUI provides a series of extended capabilities based on TypeScript to declaratively describe the GUIs of an application and the interaction between GUI components. 2300 2301 2302### ArkUI Example 2303 2304[MVVM code example](../ui/state-management/arkts-mvvm.md#example) provides a complete ArkUI-based application to demonstrate its GUI programming features. 2305 2306For more details about ArkUI features, see [Basic Syntax Overview](../ui/state-management/arkts-basic-syntax-overview.md). 2307