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