1# ArkTS Migration Background
2
3This chapter explains why it makes sense to migrate from the standard TypeScript to ArkTS. In general, there are two reasons for doing this:
4
5## Program Stability
6
7Dynamically typed languages like JavaScript are very good at allowing programs to write code fast. At the same time, these languages are
8notorious for unexpected runtime errors. For example, a developer may forget to check some value for `undefined`, and as a result of this, the program may crash, which causes inconvenience to the users. Detecting such issues during development time would be much more beneficial. TypeScript helps greatly here: It allows to annotate the code with types, and many errors will be detected by the compiler, prior to deployment and usage of the code. However, even TypeScript has limitations and sometimes permits to annotate the code with types “loosely”, which still leaves a gap for runtime errors. ArkTS tries to overcome this drawback: It enforces static typing for even stricter type checking and less runtime errors.
9
10The following case demonstrates how we can improve stability and correctness of our code by enforcing stricter type checking in ArkTS.
11
12
13**Explicit Initialization of Fields for Better Stability**
14
15ArkTS 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.
16
17Let’s take a look at the following TypeScript code:
18
19```typescript
20class Person {
21  name: string // undefined
22
23  setName(n: string): void {
24    this.name = n
25  }
26
27  getName(): string {
28  // Return type "string" hides from the developers the fact that name can be undefined.
29  // The most correct would be to write the return type as "string | undefined". By doing so
30  // we tell the users of our API about all possible return values.
31    return this.name
32  }
33}
34
35let buddy = new Person()
36// Let's assume that the developer forgets to call setName:
37// buddy.setName("John")
38buddy.getName().length; // runtime exception: name is undefined
39```
40
41Since ArkTS requires explicit initialization, the code looks like this:
42
43```typescript
44class Person {
45  name: string = ''
46
47  setName(n: string): void {
48    this.name = n
49  }
50
51  // The type is string in all cases, null and undefined are impossible.
52  getName(): string {
53    return this.name
54  }
55}
56
57let buddy = new Person()
58// Let's assume that the developer forgets to call setName:
59// buddys.setName("John")
60buddy.getName().length; // 0, no runtime error
61```
62
63If `name` can be `undefined`, this is also should be specified explicitly:
64
65```typescript
66class Person {
67    name ?: string // The field may be undefined
68
69    setName(n: string): void {
70        this.name = n
71    }
72
73    // Compile-time error:
74    // name can be "undefined", so we cannot say to those who use this API
75    // that it returns only strings:
76    getNameWrong(): string {
77        return this.name
78    }
79
80    getName(): string | undefined { // Return type matches the type of name
81        return this.name
82    }
83}
84
85let buddy = new Person()
86// Let's assume that the developer forgets to call setName:
87// buddy.setName("John")
88
89// Compile-time(!) error: Compiler suspects that we
90// may possibly access something undefined and won't build the code:
91buddy.getName().length; // The code won't build and run
92
93buddy.getName()?.length; // Builds ok, no runtime error
94```
95
96
97
98## Program Performance
99
100To ensure correctness of the program, dynamically languages have to check actual types of objects when the program actually runs. Back to our example, JavaScript does not allow to read a property from `undefined`. But the only way to check if some value is `undefined` is to perform a runtime check, that all JavaScript engines do: if the value is not `undefined`, the property is read, otherwise an exception is thrown. Modern engines can optimize such checks greatly, but these checks cannot be eliminated completely, which leads to code slowdown. Since the standard TypeScript compiles to JavaScript, the code written in TypeScript has exactly the same issues as described above. ArkTS addresses this problem. Since static typing is enforced, ArkTS compiles the program not to JavaScript, but to ARK bytecode, which is faster to execute and easier to optimize even further.
101
102
103**Null Safety**
104
105Let’s take a look at the following code:
106
107```typescript
108function notify(who: string, what: string) {
109  console.log(`Dear ${who}, a message for you: ${what}`)
110}
111
112notify('Jack', 'You look great today')
113```
114
115In most cases, the `notify` function will take two string variables as an input and produces a new string. However, what if we pass some “special” values to the function, for example `notify(null, undefined)`? The program will continue to work, the output will be as expected (`Dear null, a message for you: undefined`), so from the first glance everything is fine. But please note that the engine that runs our code should always check for such special cases to ensure correct behavior. In pseudocode, something like this happens:
116
117```typescript
118function __internal_tostring(s: any): string {
119  if (typeof s === 'string')
120    return s
121  if (s === undefined)
122    return 'undefined'
123  if (s === null)
124    return 'null'
125  // ...
126}
127```
128
129Now imagine that our `notify` function is a part of some complex heavy-loaded system which sends real notifications instead of just writing to the log. In
130this scenario, executing all these checks from our `__internal_tostring` function may turn into a performance problem.
131
132But what if we could somehow guarantee to our exectuion engine that the only values that are passed to the `notify` function are “real” strings, but not
133some “special” values like `null` or `undefined`? In this case, checks like `__internal_tostring` become redundant because when we execute the program
134we are 100% sure that there will be no corner cases. For this particular case this mechanism would be called “null-safety”, i.e. guarantee that `null` is
135not a valid value of the `string` type. If we had such feature, the code would not simply build:
136
137```typescript
138function notify(who: string, what: string) {
139  console.log(`Dear ${who}, a message for you: ${what}`)
140}
141
142notify('Jack', 'You look great today')
143notify(null, undefined) // Compile-time error
144```
145
146In TypeScript such behavior can be turned on by a special compiler flag called `strictNullChecks`. But since the standard TypeScript is compiled to JavaScript, which does not have such feature, “strict null checks” work only in compile-time, for better type checking. However, ArkTS considers null-safety a very
147important feature from both stability and performance points of view. That’s why it is enforced in the language and the example above always produces
148compile-time errors. In exchange, we give our running engine much more information and guarantees about possible type values, which helps better optimize performance.
149
150## .ets Code Compatibility
151
152Prior to API version 10, ArkTS (.ets file) completely adopted the syntax of standard TS. Since API version 10, the ArkTS syntax rules are clearly defined based on the preceding design considerations. In addition, the SDK adds the ArkTS syntax validation for .ets files to the compilation process, and prompts you to adapt to the new ArkTS syntax through warnings or errors.
153
154Syntax issues are classified as warning or error, depending on the **compatibleSdkVersion** of the project:
155
156  - In compatible mode, where the value of **compatibleSdkVersion** is greater than or equal to 10, syntax issues are reported as errors and will block the compilation process. The compilation can be successful only after the ArkTS syntax is fully adapted.
157  - In compatible mode, where the value of **compatibleSdkVersion** is smaller than 10, syntax issues are reported as warnings and will not block the compilation process.
158
159
160## ArkCompiler Runtime Compatibility with TS/JS
161
162The OpenHarmony SDK of API version 11 uses TypeScript 4.9.5, with the **target** field of **es2017**. In the application, you can use the syntax of ECMA2017+ for TS/JS development.
163
164**Application Environment Restrictions**
165
1661. Force the use of strict mode (use strict)
1672. Prohibit the use of `eval()`
1683. Prohibit the use of `with() {}`
1694. Prohibit creating functions with strings as code
170
171**Differences from Standard TS/JS**
172
173In standard TS/JS, the number format of JSON, the decimal point must be followed by a number. Scientific notation such as `2.e3` is not allowed and throws `SyntaxError`. In the ArkCompiler Runtime, this type of scientific notation is allowed.
174