1# TypeScript to ArkTS Cookbook
2
3Welcome to the "TypeScript to ArkTS cookbook". This document gives you short
4recipes to rewrite your standard TypeScript code to ArkTS. Although ArkTS is
5designed to be close to TypeScript, some limitations were added for the sake of
6performance. As a result, all TypeScript features can be divided into the following
7categories:
8
9- **Fully supported features**: The original code requires no modification
10   at all. According to our measurements, projects that already follow the
11   best TypeScript practices can keep 90% to 97% of their codebase intact.
12- **Partially supported features**: Some minor code refactoring is needed.
13   Example: The keyword `let` must be used in place of `var` to declare
14   variables. Your code will remain a valid TypeScript code
15   after rewriting by our recipes.
16- **Unsupported features**: A greater code refactoring effort is required.
17   Example: The type `any` is unsupported, and you need to introduce explicit
18   typing to your code everywhere `any` is used.
19
20The document is built on the feature-by-feature basis, and if you do not
21find a specific feature, then you can safely consider it **fully supported**. Otherwise,
22a recipe will give you a suggestion on how to rewrite your code and work
23around an unsupported case. For example, the custom decorators supported by ArkTS have the same syntax as those supported by TypeScript.
24
25**Recipe Explained**
26
27The original TypeScript code contains the keyword `var`:
28
29```typescript
30function addTen(x: number): number {
31  var ten = 10
32  return x + ten
33}
34```
35
36The code must be rewritten as follows:
37
38```typescript
39// Important! This is still valid TypeScript code.
40function addTen(x: number): number {
41  let ten = 10
42  return x + ten
43}
44```
45**Severity Levels**
46
47Each recipe is marked with the the severity level. Supported values:
48
49- **Severity: error**: The recipe should be followed, otherwise the program
50  will fail to compile.
51- **Severity: warning**: It is highly recommended to follow the recipe. Although
52  violating the recipe does not currently affect the compilation, in future
53  versions, it will cause compilation to fail.
54
55**Status of Unsupported Features**
56
57Currently, unsupported features are mainly either of the following:
58
59- Features relate to dynamic typing that degrades runtime performance
60- Features that require extra support in the compiler, thereby degrading project build time
61
62However, the ArkTS team reserves the right to reconsider the list and
63**shrink** it in the future releases based on the feedback from developers
64and real-world data experiments.
65
66## Recipes Summarized
67
68This document provides an informal summary of TypeScript features that ArkTS either
69can support with limitations, or cannot support. See [Recipes](#recipes) for the
70full list with more detailed code examples and workaround suggestions.
71
72### Static Typing Is Enforced
73
74ArkTS was designed with the following goals in mind:
75
76- ArkTS programs must be easy for developers to read and understand because
77  the code is read more often than written.
78- ArkTS must execute fast and consume as little power as possible because
79  it is particularly critical on mobile devices that ArkTS targets.
80
81One of the most important features of ArkTS that helps achieving both goals
82is static typing. If a program is statically typed (all types
83are known at compile time), it is much easier to understand what data
84structures are used in the code. Since all types are known before the program
85actually runs, the compiler can verify code correctness, thereby
86eliminating many runtime type checks and improving performance.
87
88Therefore, the usage of the type `any` in ArkTS is prohibited.
89
90**Example**
91
92```typescript
93// Not supported:
94let res: any = some_api_function('hello', 'world')
95// What is `res`? A numeric error code, a string, or an object?
96// How should we work with it?
97// Supported:
98class CallResult {
99  public succeeded(): boolean { ... }
100  public errorMessage(): string { ... }
101}
102
103let res: CallResult = some_api_function('hello', 'world')
104if (!res.succeeded()) {
105  console.log('Call failed: ' + res.errorMessage())
106}
107```
108
109According to our measurements, `any` is already not welcome in TypeScript. It is used in approximately 1% of
110TypeScript codebases. Moreover, today's code linters (for example, ESLint) include a set
111of rules that prohibit the usage of `any`. Prohibiting `any` results in a strong positive impact on performance at the cost of low-effort code refactoring.
112
113### Changing Object Layout in Runtime Is Prohibited
114
115To achieve maximum performance benefits, ArkTS requires the layout of objects
116to remain unchanged during program execution. In other words, it is prohibited to:
117
118- Add new properties or methods to objects.
119- Delete existing properties or methods from objects.
120- Assign values of arbitrary types to object properties.
121
122It is noteworthy that many such operations are already prohibited by the TypeScript
123compiler. However, it can still be "tricked", for example, by `as any` casting that
124ArkTS does not support (see the detailed example below).
125
126**Example**
127
128```typescript
129class Point {
130  public x: number = 0
131  public y: number = 0
132
133  constructor(x: number, y: number) {
134    this.x = x
135    this.y = y
136  }
137}
138
139// It is impossible to delete a property from the object. It is guaranteed that all Point objects have the property x.
140let p1 = new Point(1.0, 1.0)
141delete p1.x           // Compile-time error in TypeScript and ArkTS
142delete (p1 as any).x  // OK in TypeScript; compile-time error in ArkTS
143
144// Class Point does not define any property named `z`, and it is impossible to add it while the program runs.
145let p2 = new Point(2.0, 2.0)
146p2.z = 'Label';           // Compile-time error in TypeScript and ArkTS
147(p2 as any).z = 'Label'   // OK in TypeScript; compile-time error in ArkTS
148
149// It is guaranteed that all Point objects have only properties x and y, it is impossible to generate some arbitrary identifier and use it as a new property:
150let p3 = new Point(3.0, 3.0)
151let prop = Symbol();     // OK in TypeScript; compile-time error in ArkTS
152(p3 as any)[prop] = p3.x // OK in TypeScript; compile-time error in ArkTS
153p3[prop] = p3.x          // Compile-time error in TypeScript and ArkTS
154
155// It is guaranteed that all Point objects have properties x and y of type number, so assigning a value of any other type is impossible:
156let p4 = new Point(4.0, 4.0)
157p4.x = 'Hello!';         // Compile-time error in TypeScript and ArkTS
158(p4 as any).x = 'Hello!' // OK in TypeScript; compile-time error in ArkTS
159
160// Usage of Point objects which is compliant with the class definition:
161function distance(p1: Point, p2: Point): number {
162  return Math.sqrt(
163    (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)
164  )
165}
166let p5 = new Point(5.0, 5.0)
167let p6 = new Point(6.0, 6.0)
168console.log('Distance between p5 and p6: ' + distance(p5, p6))
169```
170
171Unpredictable changing of object layout contradicts both good readability and
172good performance of code. Indeed, having class definition at one place and
173modifying actual object layout elsewhere is confusing and error-prone from the
174developer's point of view. It opposes the idea of static typing
175and requires extra runtime support that causes undesired execution overhead.
176
177According to our observations and experiments, this feature is already not
178welcome in TypeScript. It is used in a marginal number of real-world projects,
179and state-of-the-art linters have rules to prohibit its usage.
180
181Prohibiting runtime changes to object layouts results in a
182strong positive impact on performance at the cost of low-effort refactoring.
183
184### Semantics of Operators Is Restricted
185
186To achieve better performance and encourage developers to write clearer code,
187ArkTS restricts the semantics of some operators. An example is
188given below, and the full list of restrictions is outlined in [Recipes](#recipes).
189
190**Example**
191
192```typescript
193// Unary `+` is defined only for numbers, but not for strings:
194let t = +42; // OK
195let s = +'42'; // Compile-time error
196```
197
198Loading language operators with extra semantics complicates the language
199specification, and forces developers to remember all possible corner cases with
200appropriate handling rules. Besides, in certain cases it causes some undesired
201runtime overhead.
202
203According to our observations and experiments, this feature is not popular in TypeScript. It is used in less than 1% of real-world codebases, and such cases are easy to refactor. Restricting the operator semantics results in a clearer and more performant at the cost of low-effort changes in code.
204
205### Structural Typing Is Not Supported (Yet)
206
207Assuming that two unrelated classes `T` and `U` have the same public API:
208
209```typescript
210class T {
211  public name: string = ''
212
213  public greet(): void {
214    console.log('Hello, ' + this.name)
215  }
216}
217
218class U {
219  public name: string = ''
220
221  public greet(): void {
222    console.log('Greetings, ' + this.name)
223  }
224}
225```
226
227Can we assign a value of `T` to a variable of `U`?
228
229```typescript
230let u: U = new T() // Is this allowed?
231```
232
233Can we pass a value of `T` to a function that accepts a parameter of `U`?
234
235```typescript
236function greeter(u: U) {
237  console.log('To ' + u.name)
238  u.greet()
239}
240
241let t: T = new T()
242greeter(t) // Is this allowed?
243```
244
245In other words, which approach will we take:
246
247- `T` and `U` are not related by inheritance or any common interface, but
248  they are "somewhat equivalent" since they have the same public API, and so
249  the answer to both questions above is "yes".
250- `T` and `U` are not related by inheritance or any common interface, and
251  always must be considered as totally different types, and so the answer to
252  both questions above is "no".
253
254The languages that take the first approach are said to support structural
255typing, whereas the languages that take the second approach do not support it.
256Currently, TypeScript supports structural typing, and ArkTS does not.
257
258It is debatable whether structural typing helps to produce code that
259is clearer and more understandable, and both *pro* and *contra* arguments can
260be found. Why not just support it then?
261
262The answer is that supporting structural typing is a major feature that needs
263a lot of considerations and careful implementation in language specification,
264compiler, and runtime. More importantly, in case if ArkTS, which enforces static
265typing (see above), runtime support for structural typing implies performance
266overhead. So since functionally correct and performant implementation requires
267taking that many aspects into account, the support to this feature is postponed.
268
269The ArkTS team is ready to reconsider based on real-world scenarios and feedback.
270More cases and suggested workarounds can be found in [Recipes](#recipes).
271
272## Recipes
273
274### Recipe: Objects with Property Names That Are Not Identifiers Are Not Supported
275
276**Rule:** `arkts-identifiers-as-prop-names`
277
278**Severity: error**
279
280ArkTS does not support objects with name properties that are numbers or
281strings. Exceptions are string type enumeration constants and string literal. Use classes to access data by property names. Use arrays to access
282data by numeric indices.
283
284**TypeScript**
285
286```typescript
287var x = { 'name': 'x', 2: '3' }
288
289console.log(x['name'])
290console.log(x[2])
291```
292
293**ArkTS**
294
295```typescript
296class X {
297  public name: string = ''
298}
299let x: X = { name: 'x' }
300console.log(x.name)
301
302let y = ['a', 'b', 'c']
303console.log(y[2])
304
305// If you still need a container to store keys of different types, use Map<Object, some_type>.
306let z = new Map<Object, string>()
307z.set('name', '1')
308z.set(2, '2')
309console.log(z.get('name'))
310console.log(z.get(2))
311
312enum Test {
313  A = 'aaa',
314  B = 'bbb'
315}
316
317let obj: Record<string, number> = {
318  [Test.A]: 1,   // string type enumeration constants
319  [Test.B]: 2,   // string type enumeration constants
320  ['value']: 3   // string literal
321}
322```
323
324### Recipe: `Symbol()` Is Not Supported
325
326**Rule:** `arkts-no-symbol`
327
328**Severity: error**
329
330TypeScript uses the `Symbol()` API among other things to generate
331unique property names at runtime. ArkTS does not support the `Symbol()` API
332because its most popular use cases make no sense in the statically typed
333environment. In particular, the object layout is defined at compile time
334and cannot be changed at runtime.
335
336Only `Symbol.iterator` is supported.
337
338### Recipe: Private `#` Identifiers Are Not Supported
339
340**Rule:** `arkts-no-private-identifiers`
341
342**Severity: error**
343
344ArkTS does not use private identifiers starting with the symbol `#`. Use the keyword  `private` instead.
345
346**TypeScript**
347
348```typescript
349class C {
350  #foo: number = 42
351}
352```
353
354**ArkTS**
355
356```typescript
357class C {
358  private foo: number = 42
359}
360```
361
362### Recipe: Use Unique Names for Types and Namespaces
363
364**Rule:** `arkts-unique-names`
365
366**Severity: error**
367
368Names for all types (classes, interfaces, and enums) and namespaces must be unique and distinct from other names such as, variable names, and function names.
369
370**TypeScript**
371
372```typescript
373let X: string
374type X = number[] // Type alias with the same name as the variable
375```
376
377**ArkTS**
378
379```typescript
380let X: string
381type T = number[] // X is not allowed here to avoid name collisions.
382```
383
384### Recipe: Use `let` Instead of `var`
385
386**Rule:** `arkts-no-var`
387
388**Severity: error**
389
390ArkTS does not support `var`. Use `let` instead.
391
392**TypeScript**
393
394```typescript
395function f(shouldInitialize: boolean) {
396  if (shouldInitialize) {
397     var x = 'b'
398  }
399  return x
400}
401
402console.log(f(true))  // b
403console.log(f(false)) // undefined
404
405let upperLet = 0
406{
407  var scopedVar = 0
408  let scopedLet = 0
409  upperLet = 5
410}
411scopedVar = 5 // Visible
412scopedLet = 5 // Compile-time error
413```
414
415**ArkTS**
416
417```typescript
418function f(shouldInitialize: boolean): string {
419  let x: string = 'a';
420  if (shouldInitialize) {
421    x = 'b';
422  }
423  return x;
424}
425
426console.log(f(true));  // b
427console.log(f(false)); // a
428
429let upperLet = 0
430let scopedVar = 0
431{
432  let scopedLet = 0
433  upperLet = 5
434}
435scopedVar = 5
436scopedLet = 5 // Compile-time error
437```
438
439### Recipe: Use Explicit Types Instead of `any` or `unknown`
440
441**Rule:** `arkts-no-any-unknown`
442
443**Severity: error**
444
445ArkTS does not support the types `any` and `unknown`. Specify types explicitly.
446
447**TypeScript**
448
449```typescript
450let value1: any
451value1 = true
452value1 = 42
453
454let value2: unknown
455value2 = true
456value2 = 42
457```
458
459**ArkTS**
460
461```typescript
462let value_b: boolean = true // OR: let value_b = true
463let value_n: number = 42 // OR: let value_n = 42
464let value_o1: Object = true
465let value_o2: Object = 42
466```
467
468### Recipe: Use `class` Instead of a Type with a Call Signature
469
470**Rule:** `arkts-no-call-signatures`
471
472**Severity: error**
473
474ArkTS does not support call signatures in object types. Use `class` instead.
475
476**TypeScript**
477
478```typescript
479type DescribableFunction = {
480  description: string
481  (someArg: string): string // call signature
482}
483
484function doSomething(fn: DescribableFunction): void {
485  console.log(fn.description + ' returned ' + fn(''))
486}
487```
488
489**ArkTS**
490
491```typescript
492class DescribableFunction {
493  description: string
494  public invoke(someArg: string): string {
495    return someArg
496  }
497  constructor() {
498    this.description = 'desc'
499  }
500}
501
502function doSomething(fn: DescribableFunction): void {
503  console.log(fn.description + ' returned ' + fn.invoke(''))
504}
505
506doSomething(new DescribableFunction())
507```
508
509### Recipe: Use `class` Instead of a Type with a Constructor Signature
510
511**Rule:** `arkts-no-ctor-signatures-type`
512
513**Severity: error**
514
515ArkTS does not support constructor signatures in object types. Use `class` instead.
516
517**TypeScript**
518
519```typescript
520class SomeObject {}
521
522type SomeConstructor = {
523  new (s: string): SomeObject
524}
525
526function fn(ctor: SomeConstructor) {
527  return new ctor('hello')
528}
529```
530
531**ArkTS**
532
533```typescript
534class SomeObject {
535  public f: string
536  constructor (s: string) {
537    this.f = s
538  }
539}
540
541function fn(s: string): SomeObject {
542  return new SomeObject(s)
543}
544```
545
546### Recipe: Only One Static Block Is Supported
547
548**Rule:** `arkts-no-multiple-static-blocks`
549
550**Severity: error**
551
552ArkTS does not allow several static blocks for class initialization. Combine static block statements into one static block.
553
554**TypeScript**
555
556```typescript
557class C {
558  static s: string
559
560  static {
561    C.s = 'aa'
562  }
563  static {
564    C.s = C.s + 'bb'
565  }
566}
567```
568
569**ArkTS**
570
571```typescript
572class C {
573  static s: string
574
575  static {
576    C.s = 'aa'
577    C.s = C.s + 'bb'
578  }
579}
580```
581
582**NOTE**
583
584Currently, the static block syntax is not supported. This rule must be followed in .ets files when the syntax is supported.
585
586### Recipe: Indexed Signatures Are Not Supported
587
588**Rule:** `arkts-no-indexed-signatures`
589
590**Severity: error**
591
592ArkTS does not allow indexed signatures. Use arrays instead.
593
594**TypeScript**
595
596```typescript
597// Interface with an indexed signature:
598interface StringArray {
599  [index: number]: string
600}
601
602function getStringArray(): StringArray {
603  return ['a', 'b', 'c']
604}
605
606const myArray: StringArray = getStringArray()
607const secondItem = myArray[1]
608```
609
610**ArkTS**
611
612```typescript
613class X {
614  public f: string[] = []
615}
616
617let myArray: X = new X()
618const secondItem = myArray.f[1]
619```
620
621### Recipe: Use Inheritance Instead of Intersection Types
622
623**Rule:** `arkts-no-intersection-types`
624
625**Severity: error**
626
627Currently, ArkTS does not support intersection types. Use inheritance as a workaround.
628
629**TypeScript**
630
631```typescript
632interface Identity {
633  id: number
634  name: string
635}
636
637interface Contact {
638  email: string
639  phoneNumber: string
640}
641
642type Employee = Identity & Contact
643```
644
645**ArkTS**
646
647```typescript
648interface Identity {
649  id: number
650  name: string
651}
652
653interface Contact {
654  email: string
655  phoneNumber: string
656}
657
658interface Employee extends Identity,  Contact {}
659```
660
661### Recipe: Type Notation Using `this` Is Not Supported
662
663**Rule:** `arkts-no-typing-with-this`
664
665**Severity: error**
666
667ArkTS does not support type notation using the `this` keyword. Use the explicit type instead.
668
669**TypeScript**
670
671```typescript
672interface ListItem {
673  getHead(): this
674}
675
676class C {
677  n: number = 0
678
679  m(c: this) {
680    // ...
681  }
682}
683```
684
685**ArkTS**
686
687```typescript
688interface ListItem {
689  getHead(): ListItem
690}
691
692class C {
693  n: number = 0
694
695  m(c: C) {
696    // ...
697  }
698}
699```
700
701### Recipe: Conditional Types Are Not Supported
702
703**Rule:** `arkts-no-conditional-types`
704
705**Severity: error**
706
707ArkTS does not support conditional type aliases. Introduce a new type with constraints explicitly, or rewrite logic using `Object`.
708The keyword `infer` is not supported.
709
710**TypeScript**
711
712```typescript
713type X<T> = T extends number ? T: never
714type Y<T> = T extends Array<infer Item> ? Item: never
715```
716
717**ArkTS**
718
719```typescript
720// Provide explicit constraints within type alias.
721type X1<T extends number> = T
722
723// Rewrite with Object. Less type control requires more type checking for safety.
724type X2<T> = Object
725
726// Item has to be used as a generic parameter and needs to be properly instantiated.
727type YI<Item, T extends Array<Item>> = Item
728```
729
730### Recipe: Declaring Fields in `constructor` Is Not Supported
731
732**Rule:** `arkts-no-ctor-prop-decls`
733
734**Severity: error**
735
736ArkTS does not support declaring class fields in `constructor`. Declare class fields inside the `class` declaration instead.
737
738**TypeScript**
739
740```typescript
741class Person {
742  constructor(
743    protected ssn: string,
744    private firstName: string,
745    private lastName: string
746  ) {
747    this.ssn = ssn
748    this.firstName = firstName
749    this.lastName = lastName
750  }
751
752  getFullName(): string {
753    return this.firstName + ' ' + this.lastName
754  }
755}
756```
757
758**ArkTS**
759
760```typescript
761class Person {
762  protected ssn: string
763  private firstName: string
764  private lastName: string
765
766  constructor(ssn: string, firstName: string, lastName: string) {
767    this.ssn = ssn
768    this.firstName = firstName
769    this.lastName = lastName
770  }
771
772  getFullName(): string {
773    return this.firstName + ' ' + this.lastName
774  }
775}
776```
777
778### Recipe: Constructor Signatures Are Not Supported in Interfaces
779
780**Rule:** `arkts-no-ctor-signatures-iface`
781
782**Severity: error**
783
784ArkTS does not support constructor signatures. Use methods instead.
785
786**TypeScript**
787
788```typescript
789interface I {
790  new (s: string): I
791}
792
793function fn(i: I) {
794  return new i('hello')
795}
796```
797
798**ArkTS**
799
800```typescript
801interface I {
802  create(s: string): I
803}
804
805function fn(i: I) {
806  return i.create('hello')
807}
808```
809
810### Recipe: Indexed Access Types Are Not Supported
811
812**Rule:** `arkts-no-aliases-by-index`
813
814**Severity: error**
815
816ArkTS does not support indexed access types. Use the type name instead.
817
818### Recipe: Indexed Access Is Not Supported for Fields
819
820**Rule:** `arkts-no-props-by-index`
821
822**Severity: error**
823
824ArkTS does not support dynamic field declaration and access. Declare all
825object fields immediately in the class. Access only those class fields
826that are either declared in the class, or accessible via inheritance. Accessing
827any other fields is prohibited, and causes compile-time errors.
828
829To access a field, use the `obj.field` syntax. Indexed access (`obj["field"]`)
830is not supported. An exception is all typed arrays from the standard library
831(for example, `Int32Array`), which support access to their elements through the
832`container[index]` syntax.
833**TypeScript**
834
835```typescript
836class Point {
837  x: string = ''
838  y: string = ''
839}
840let p: Point = {x: '1', y: '2'}
841console.log(p['x'])
842
843class Person {
844  name: string = ''
845  age: number = 0; // A semicolon is required here.
846  [key: string]: string | number
847}
848
849let person: Person = {
850  name: 'John',
851  age: 30,
852  email: '***@example.com',
853  phoneNumber: '18*********',
854}
855```
856
857**ArkTS**
858
859```typescript
860class Point {
861  x: string = ''
862  y: string = ''
863}
864let p: Point = {x: '1', y: '2'}
865console.log(p.x)
866
867class Person {
868  name: string
869  age: number
870  email: string
871  phoneNumber: string
872
873  constructor(name: string, age: number, email: string,
874        phoneNumber: string) {
875    this.name = name
876    this.age = age
877    this.email = email
878    this.phoneNumber = phoneNumber
879  }
880}
881
882let person = new Person('John', 30, '***@example.com', '18*********');
883console.log(person['name']);     // Compile-time error
884console.log(person.unknownProperty); // Compile-time error
885
886let arr = new Int32Array(1);
887arr[0];
888```
889
890### Recipe: Structural Typing Is Not Supported
891
892**Rule:** `arkts-no-structural-typing`
893
894**Severity: error**
895
896Currently, ArkTS does not support structural typing. This means that  the compiler
897cannot compare public APIs of two types and decide whether they are
898identical. Use other mechanisms (inheritance, interfaces, or type aliases)
899instead.
900
901**TypeScript**
902
903```typescript
904interface I1 {
905  f(): string
906}
907
908interface I2 { // I2 is structurally equivalent to I1.
909  f(): string
910}
911
912class X {
913  n: number = 0
914  s: string = ''
915}
916
917class Y { // Y is structurally equivalent to X.
918  n: number = 0
919  s: string = ''
920}
921
922let x = new X()
923let y = new Y()
924
925console.log('Assign X to Y')
926y = x
927
928console.log('Assign Y to X')
929x = y
930
931function foo(x: X) {
932  console.log(x.n + x.s)
933}
934
935// X and Y are equivalent because their public API is equivalent. Therefore, the second call is allowed.
936foo(new X())
937foo(new Y())
938```
939
940**ArkTS**
941
942```typescript
943interface I1 {
944  f(): string
945}
946
947type I2 = I1 // I2 is an alias for I1.
948
949class B {
950  n: number = 0
951  s: string = ''
952}
953
954// D is derived from B, which explicitly set subtype/supertype relations.
955class D extends B {
956  constructor() {
957    super()
958  }
959}
960
961let b = new B()
962let d = new D()
963
964console.log('Assign D to B')
965b = d // OK. B is the superclass of D.
966
967// An attempt to assign b to d will result in a compile-time error.
968// d = b
969
970interface Z {
971   n: number
972   s: string
973}
974
975// X implements interface Z, which makes relation between X and Y explicit.
976class X implements Z {
977  n: number = 0
978  s: string = ''
979}
980
981// Y implements interface Z, which makes relation between X and Y explicit.
982class Y implements Z {
983  n: number = 0
984  s: string = ''
985}
986
987let x: Z = new X()
988let y: Z = new Y()
989
990console.log('Assign X to Y')
991y = x // ok, both are of the same type
992
993console.log('Assign Y to X')
994x = y // ok, both are of the same type
995
996function foo(c: Z): void {
997  console.log(c.n + c.s)
998}
999
1000// X and Y implement the same interface. Therefore both calls are allowed.
1001foo(new X())
1002foo(new Y())
1003```
1004
1005### Recipe: Type Inference in Case of Generic Function Calls Is Limited
1006
1007**Rule:** `arkts-no-inferred-generic-params`
1008
1009**Severity: error**
1010
1011ArkTS allows to omit generic type parameters if it is possible to infer
1012the concrete types from the parameters passed to the function. A compile-time
1013error occurs otherwise. In particular, inference of generic type parameters
1014based only on function return types is prohibited.
1015
1016**TypeScript**
1017
1018```typescript
1019function choose<T>(x: T, y: T): T {
1020  return Math.random() < 0.5 ? x: y
1021}
1022
1023let x = choose(10, 20)   // OK. choose<number>(...) is inferred.
1024let y = choose('10', 20) // Compile-time error
1025
1026function greet<T>(): T {
1027  return 'Hello' as T
1028}
1029let z = greet() // Type of T is inferred as "unknown".
1030```
1031
1032**ArkTS**
1033
1034```typescript
1035function choose<T>(x: T, y: T): T {
1036  return Math.random() < 0.5 ? x: y
1037}
1038
1039let x = choose(10, 20)   // OK. choose<number>(...) is inferred.
1040let y = choose('10', 20) // Compile-time error
1041
1042function greet<T>(): T {
1043  return 'Hello' as T
1044}
1045let z = greet<string>()
1046```
1047
1048### Recipe: Object Literal Must Correspond to Some Explicitly Declared Class or Interface
1049
1050**Rule:** `arkts-no-untyped-obj-literals`
1051
1052**Severity: error**
1053
1054ArkTS supports usage of object literals if the compiler can infer to the classes or interfaces that such literals correspond to. Otherwise, a compile-time error occurs.
1055
1056Using literals to initialize classes and interfaces is specifically not supported in the following contexts:
1057
1058* Initialization of anything that has `any`, `Object`, or `object` type
1059* Initialization of classes or interfaces with methods
1060* Initialization of classes which declare a `constructor` with parameters
1061* Initialization of classes with `readonly` fields
1062
1063**Example 1**
1064
1065**TypeScript**
1066
1067```typescript
1068let o1 = {n: 42, s: 'foo'}
1069let o2: Object = {n: 42, s: 'foo'}
1070let o3: object = {n: 42, s: 'foo'}
1071
1072let oo: Object[] = [{n: 1, s: '1'}, {n: 2, s: '2'}]
1073```
1074
1075**ArkTS**
1076
1077```typescript
1078class C1 {
1079  n: number = 0
1080  s: string = ''
1081}
1082
1083let o1: C1 = {n: 42, s: 'foo'}
1084let o2: C1 = {n: 42, s: 'foo'}
1085let o3: C1 = {n: 42, s: 'foo'}
1086
1087let oo: C1[] = [{n: 1, s: '1'}, {n: 2, s: '2'}]
1088```
1089
1090**Example 2**
1091
1092**TypeScript**
1093
1094```typescript
1095class C2 {
1096  s: string
1097  constructor(s: string) {
1098    this.s = 's =' + s
1099  }
1100}
1101let o4: C2 = {s: 'foo'}
1102```
1103
1104**ArkTS**
1105
1106```typescript
1107class C2 {
1108  s: string
1109  constructor(s: string) {
1110    this.s = 's =' + s
1111  }
1112}
1113let o4 = new C2('foo')
1114```
1115
1116**Example 3**
1117
1118**TypeScript**
1119
1120```typescript
1121class C3 {
1122  readonly n: number = 0
1123  readonly s: string = ''
1124}
1125let o5: C3 = {n: 42, s: 'foo'}
1126```
1127
1128**ArkTS**
1129
1130```typescript
1131class C3 {
1132  n: number = 0
1133  s: string = ''
1134}
1135let o5: C3 = {n: 42, s: 'foo'}
1136```
1137
1138**Example 4**
1139
1140**TypeScript**
1141
1142```typescript
1143abstract class A {}
1144let o6: A = {}
1145```
1146
1147**ArkTS**
1148
1149```typescript
1150abstract class A {}
1151class C extends A {}
1152let o6: C = {} // Or let o6: C = new C()
1153```
1154
1155**Example 5**
1156
1157**TypeScript**
1158
1159```typescript
1160class C4 {
1161  n: number = 0
1162  s: string = ''
1163  f() {
1164    console.log('Hello')
1165  }
1166}
1167let o7: C4 = {n: 42, s: 'foo', f: () => {}}
1168```
1169
1170**ArkTS**
1171
1172```typescript
1173class C4 {
1174  n: number = 0
1175  s: string = ''
1176  f() {
1177    console.log('Hello')
1178  }
1179}
1180let o7 = new C4()
1181o7.n = 42
1182o7.s = 'foo'
1183```
1184
1185**Example 6**
1186
1187**TypeScript**
1188
1189```typescript
1190class Point {
1191  x: number = 0
1192  y: number = 0
1193}
1194
1195function getPoint(o: Point): Point {
1196  return o
1197}
1198
1199// Structural typing is used to deduce that p is Point.
1200let p = {x: 5, y: 10}
1201getPoint(p)
1202
1203// A literal can be contextually (i.e., implicitly) typed as Point.
1204getPoint({x: 5, y: 10})
1205```
1206
1207**ArkTS**
1208
1209```typescript
1210class Point {
1211  x: number = 0
1212  y: number = 0
1213
1214    // constructor() is used before literal initialization to create a valid object.
1215    // Since there is no other Point constructors, constructor() is automatically added by compiler.
1216}
1217
1218function getPoint(o: Point): Point {
1219  return o
1220}
1221
1222// Explicit type is required for literal initialization.
1223let p: Point = {x: 5, y: 10}
1224getPoint(p)
1225
1226// getPoint expects Point explicitly. A new instance of Point is initialized with the literal.
1227getPoint({x: 5, y: 10})
1228```
1229
1230### Recipe: Object Literals Cannot Be Used as Type Declarations
1231
1232**Rule:** `arkts-no-obj-literals-as-types`
1233
1234**Severity: error**
1235
1236ArkTS does not support the usage of object literals to declare types in place. Declare classes and interfaces explicitly instead.
1237
1238**TypeScript**
1239
1240```typescript
1241let o: {x: number, y: number} = {
1242  x: 2,
1243  y: 3
1244}
1245
1246type S = Set<{x: number, y: number}>
1247```
1248
1249**ArkTS**
1250
1251```typescript
1252class O {
1253  x: number = 0
1254  y: number = 0
1255}
1256
1257let o: O = {x: 2, y: 3}
1258
1259type S = Set<O>
1260```
1261
1262### Recipe: Array Literals Must Contain Elements of Only Inferrable Types
1263
1264**Rule:** `arkts-no-noninferrable-arr-literals`
1265
1266**Severity: error**
1267
1268Basically, ArkTS infers the type of an array literal as a union type of its
1269contents. However, a compile-time error occurs if there is at least one
1270element with a non-inferrable type (for example, untyped object literal).
1271
1272**TypeScript**
1273
1274```typescript
1275let a = [{n: 1, s: '1'}, {n: 2, s: '2'}]
1276```
1277
1278**ArkTS**
1279
1280```typescript
1281class C {
1282  n: number = 0
1283  s: string = ''
1284}
1285
1286let a1 = [{n: 1, s: '1'} as C, {n: 2, s: '2'} as C] // a1 is of type "C[]"
1287let a2: C[] = [{n: 1, s: '1'}, {n: 2, s: '2'}]    // a2 is of type "C[]"
1288```
1289
1290### Recipe: Use Arrow Functions Instead of Function Expressions
1291
1292**Rule:** `arkts-no-func-expressions`
1293
1294**Severity: error**
1295
1296ArkTS does not support function expressions. Use arrow functions instead to specify explicitly.
1297
1298**TypeScript**
1299
1300```typescript
1301let f = function (s: string) {
1302  console.log(s)
1303}
1304```
1305
1306**ArkTS**
1307
1308```typescript
1309let f = (s: string) => {
1310  console.log(s)
1311}
1312```
1313
1314### Recipe: Class Literals Are Not Supported
1315
1316**Rule:** `arkts-no-class-literals`
1317
1318**Severity: error**
1319
1320ArkTS does not support class literals. Introduce new named class types explicitly.
1321
1322**TypeScript**
1323
1324```typescript
1325const Rectangle = class {
1326  constructor(height: number, width: number) {
1327    this.height = height
1328    this.width = width
1329  }
1330
1331  height
1332  width
1333}
1334
1335const rectangle = new Rectangle(0.0, 0.0)
1336```
1337
1338**ArkTS**
1339
1340```typescript
1341class Rectangle {
1342  constructor(height: number, width: number) {
1343    this.height = height
1344    this.width = width
1345  }
1346
1347  height: number
1348  width: number
1349}
1350
1351const rectangle = new Rectangle(0.0, 0.0)
1352```
1353
1354### Recipe: Classes Cannot Be Specified in the `implements` Clause
1355
1356**Rule:** `arkts-implements-only-iface`
1357
1358**Severity: error**
1359
1360ArkTS does not allow to specify a class in the `implements` clause. Only interfaces may be specified.
1361
1362**TypeScript**
1363
1364```typescript
1365class C {
1366  foo() {}
1367}
1368
1369class C1 implements C {
1370  foo() {}
1371}
1372```
1373
1374**ArkTS**
1375
1376```typescript
1377interface C {
1378  foo(): void
1379}
1380
1381class C1 implements C {
1382  foo() {}
1383}
1384```
1385
1386### Recipe: Reassigning Object Methods Is Not Supported
1387
1388**Rule:** `arkts-no-method-reassignment`
1389
1390**Severity: error**
1391
1392ArkTS does not support reassigning a method for objects. In the statically
1393typed languages, the layout of objects is fixed and all instances of the same
1394object must share the same code of each method.
1395
1396If you need to add specific behavior for certain objects, you can create
1397separate wrapper functions or use inheritance.
1398
1399**TypeScript**
1400
1401```typescript
1402class C {
1403  foo() {
1404    console.log('foo')
1405  }
1406}
1407
1408function bar() {
1409  console.log('bar')
1410}
1411
1412let c1 = new C()
1413let c2 = new C()
1414c2.foo = bar
1415
1416c1.foo() // foo
1417c2.foo() // bar
1418```
1419
1420**ArkTS**
1421
1422```typescript
1423class C {
1424  foo() {
1425    console.log('foo')
1426  }
1427}
1428
1429class Derived extends C {
1430  foo() {
1431    console.log('Extra')
1432    super.foo()
1433  }
1434}
1435
1436function bar() {
1437  console.log('bar')
1438}
1439
1440let c1 = new C()
1441let c2 = new C()
1442c1.foo() // foo
1443c2.foo() // foo
1444
1445let c3 = new Derived()
1446c3.foo() // Extra foo
1447```
1448### Recipe: Only the `as T` Syntax Is Supported for Type Casting
1449
1450**Rule:** `arkts-as-casts`
1451
1452**Severity: error**
1453
1454ArkTS supports the keyword `as` as the only syntax for type casting.
1455Incorrect casting causes a compile-time error or runtime `ClassCastException`.
1456The `<type>` syntax for type casting is not supported.
1457
1458Use the expression `new ...` instead of `as` if a **primitive** type
1459(such as a `number` or a `boolean`) must be cast to the reference type.
1460
1461**TypeScript**
1462
1463```typescript
1464class Shape {}
1465class Circle extends Shape {x: number = 5}
1466class Square extends Shape {y: string = 'a'}
1467
1468function createShape(): Shape {
1469  return new Circle()
1470}
1471
1472let c1 = <Circle> createShape()
1473
1474let c2 = createShape() as Circle
1475
1476// No report is provided during compilation or runtime if casting is wrong.
1477let c3 = createShape() as Square
1478console.log(c3.y) // undefined
1479
1480// Important corner case for casting primitives to the boxed counterparts:
1481// The left operand is not properly boxed here in runtime
1482// because "as" has no runtime effect in TypeScript.
1483let e1 = (5.0 as Number) instanceof Number // false
1484
1485// A Number object is created and instanceof works as expected.
1486let e2 = (new Number(5.0)) instanceof Number // True
1487```
1488
1489**ArkTS**
1490
1491```typescript
1492class Shape {}
1493class Circle extends Shape {x: number = 5}
1494class Square extends Shape {y: string = 'a'}
1495
1496function createShape(): Shape {
1497  return new Circle()
1498}
1499
1500let c2 = createShape() as Circle
1501
1502// ClassCastException is thrown during runtime.
1503let c3 = createShape() as Square
1504
1505// A Number object is created and instanceof works as expected.
1506let e2 = (new Number(5.0)) instanceof Number // True
1507```
1508
1509### Recipe: JSX Expressions Are Not Supported
1510
1511**Rule:** `arkts-no-jsx`
1512
1513**Severity: error**
1514
1515Do not use JSX since no alternative is provided to rewrite it.
1516
1517### Recipe: Unary Operators `+`, `-`, and `~` Work Only on Numbers
1518
1519**Rule:** `arkts-no-polymorphic-unops`
1520
1521**Severity: error**
1522
1523ArkTS allows unary operators to work on numeric types only. A compile-time
1524error occurs if these operators are applied to a non-numeric type. Unlike in
1525TypeScript, implicit casting of strings in this context is not supported and casting must
1526be done explicitly.
1527
1528**TypeScript**
1529
1530```typescript
1531let a = +5        // 5 as number
1532let b = +'5'      // 5 as number
1533let c = -5        // -5 as number
1534let d = -'5'      // -5 as number
1535let e = ~5        // -6 as number
1536let f = ~'5'      // -6 as number
1537let g = +'string' // NaN as number
1538
1539function returnTen(): string {
1540  return '-10'
1541}
1542
1543function returnString(): string {
1544  return 'string'
1545}
1546
1547let x = +returnTen()    // -10 as number
1548let y = +returnString() // NaN
1549```
1550
1551**ArkTS**
1552
1553```typescript
1554let a = +5        // 5 as number
1555let b = +'5'      // Compile-time error
1556let c = -5        // -5 as number
1557let d = -'5'      // Compile-time error
1558let e = ~5        // -6 as number
1559let f = ~'5'      // Compile-time error
1560let g = +'string' // Compile-time error
1561
1562function returnTen(): string {
1563  return '-10'
1564}
1565
1566function returnString(): string {
1567  return 'string'
1568}
1569
1570let x = +returnTen()    // Compile-time error
1571let y = +returnString() // Compile-time error
1572```
1573
1574### Recipe: `delete` Operator Is Not Supported
1575
1576**Rule:** `arkts-no-delete`
1577
1578**Severity: error**
1579
1580ArkTS assumes that object layout is known at compile time and cannot be
1581changed at runtime. Therefore, the operation of deleting a property makes no sense.
1582
1583**TypeScript**
1584
1585```typescript
1586class Point {
1587  x?: number = 0.0
1588  y?: number = 0.0
1589}
1590
1591let p = new Point()
1592delete p.y
1593```
1594
1595**ArkTS**
1596
1597```typescript
1598// To mimic the original semantics, you may declare a nullable type and assign null to mark the value absence.
1599
1600class Point {
1601  x: number | null = 0
1602  y: number | null = 0
1603}
1604
1605let p = new Point()
1606p.y = null
1607```
1608
1609### Recipe: `typeof` Operator Is Allowed Only in Expression Contexts
1610
1611**Rule:** `arkts-no-type-query`
1612
1613**Severity: error**
1614
1615ArkTS supports the `typeof` operator only in the expression context. Using `typeof` to specify type notations is not supported.
1616
1617**TypeScript**
1618
1619```typescript
1620let n1 = 42
1621let s1 = 'foo'
1622console.log(typeof n1) // 'number'
1623console.log(typeof s1) // 'string'
1624let n2: typeof n1
1625let s2: typeof s1
1626```
1627
1628**ArkTS**
1629
1630```typescript
1631let n1 = 42
1632let s1 = 'foo'
1633console.log(typeof n1) // 'number'
1634console.log(typeof s1) // 'string'
1635let n2: number
1636let s2: string
1637```
1638
1639### Recipe: `instanceof` Operator Is Partially Supported
1640
1641**Rule:** `arkts-instanceof-ref-types`
1642
1643**Severity: error**
1644
1645In TypeScript, the left-hand side of an `instanceof` expression must be of the type
1646`any`, an object type, or a type parameter. Otherwise, the result is `false`.
1647In ArkTS, the left-hand side of an expression may be of any reference type, for example, an object, an array, or a function. Otherwise, a compile-time error occurs. In addition, the left operand in ArkTS
1648cannot be a type. It must be an object instance.
1649
1650### Recipe: `in` Operator Is Not Supported
1651
1652**Rule:** `arkts-no-in`
1653
1654**Severity: error**
1655
1656ArkTS does not support the operator `in`. This operator makes
1657little sense since the object layout is known at compile time and cannot
1658be changed at runtime. Use `instanceof` as a workaround if you want
1659to check whether certain class members exist.
1660
1661**TypeScript**
1662
1663```typescript
1664class Person {
1665  name: string = ''
1666}
1667let p = new Person()
1668
1669let b = 'name' in p // true
1670```
1671
1672**ArkTS**
1673
1674```typescript
1675class Person {
1676  name: string = ''
1677}
1678let p = new Person()
1679
1680let b = p instanceof Person // True. "name" is guaranteed to be present.
1681```
1682
1683### Recipe: Destructuring Assignment Is Not Supported
1684
1685**Rule:** `arkts-no-destruct-assignment`
1686
1687**Severity: error**
1688
1689ArkTS does not support destructuring assignment. Use other idioms (for example, a temporary variable, where applicable) instead.
1690
1691**TypeScript**
1692
1693```typescript
1694let [one, two] = [1, 2]; // Semicolon is required here
1695[one, two] = [two, one]
1696
1697let head, tail
1698[head, ...tail] = [1, 2, 3, 4]
1699```
1700
1701**ArkTS**
1702
1703```typescript
1704let arr: number[] = [1, 2]
1705let one = arr[0]
1706let two = arr[1]
1707
1708let tmp = one
1709one = two
1710two = tmp
1711
1712let data: Number[] = [1, 2, 3, 4]
1713let head = data[0]
1714let tail: Number[] = []
1715for (let i = 1; i < data.length; ++i) {
1716  tail.push(data[i])
1717}
1718```
1719
1720### Recipe: Comma Operator `,` Is Supported Only in `for` Loops
1721
1722**Rule:** `arkts-no-comma-outside-loops`
1723
1724**Severity: error**
1725
1726ArkTS supports the comma operator `,` only in `for` loops. In other cases,
1727the comma operator is useless as it makes the execution order harder to understand.
1728
1729Please note that this rule is applied only to the "comma operator". Other cases, when
1730comma is used to delimit variable declarations or parameters of a function call, are
1731of course allowed.
1732
1733**TypeScript**
1734
1735```typescript
1736for (let i = 0, j = 0; i < 10; ++i, j += 2) {
1737  // ...
1738}
1739
1740let x = 0
1741x = (++x, x++) // 1
1742```
1743
1744**ArkTS**
1745
1746```typescript
1747for (let i = 0, j = 0; i < 10; ++i, j += 2) {
1748  // ...
1749}
1750
1751// Use the explicit execution order instead of the comma operator.
1752let x = 0
1753++x
1754x = x++
1755```
1756
1757### Recipe: Destructuring Variable Declarations Are Not Supported
1758
1759**Rule:** `arkts-no-destruct-decls`
1760
1761**Severity: error**
1762
1763ArkTS does not support destructuring variable declarations. This is a dynamic
1764feature relying on structural compatibility. In addition, names in destructuring
1765declarations must be equal to properties within destructed classes.
1766
1767**TypeScript**
1768
1769```typescript
1770class Point {
1771  x: number = 0.0
1772  y: number = 0.0
1773}
1774
1775function returnZeroPoint(): Point {
1776  return new Point()
1777}
1778
1779let {x, y} = returnZeroPoint()
1780```
1781
1782**ArkTS**
1783
1784```typescript
1785class Point {
1786  x: number = 0.0
1787  y: number = 0.0
1788}
1789
1790function returnZeroPoint(): Point {
1791  return new Point()
1792}
1793
1794// Create an intermediate object and work with it field by field without name restrictions.
1795let zp = returnZeroPoint()
1796let x = zp.x
1797let y = zp.y
1798```
1799
1800### Recipe: Type Annotation in the Catch Clause Is Not Supported
1801
1802**Rule:** `arkts-no-types-in-catch`
1803
1804**Severity: error**
1805
1806In TypeScript, the catch clause variable type annotation must be `any` or `unknown`
1807if specified. As ArkTS does not support these types, omit type annotations.
1808
1809**TypeScript**
1810
1811```typescript
1812try {
1813  // ...
1814} catch (a: unknown) {
1815  // Handle errors.
1816}
1817```
1818
1819**ArkTS**
1820
1821```typescript
1822try {
1823  // ...
1824} catch (a) {
1825  // Handle errors.
1826}
1827```
1828
1829### Recipe: `for .. in` Is Not Supported
1830
1831**Rule:** `arkts-no-for-in`
1832
1833**Severity: error**
1834
1835ArkTS does not support iteration over object contents by the
1836`for .. in` loop. For objects, iteration over properties at runtime is
1837considered redundant because object layout is known at compile time and
1838cannot change at runtime. For arrays, use the regular `for` loop for iteration.
1839
1840**TypeScript**
1841
1842```typescript
1843let a: string[] = ['1.0', '2.0', '3.0']
1844for (let i in a) {
1845  console.log(a[i])
1846}
1847```
1848
1849**ArkTS**
1850
1851```typescript
1852let a: string[] = ['1.0', '2.0', '3.0']
1853for (let i = 0; i < a.length; ++i) {
1854  console.log(a[i])
1855}
1856```
1857
1858### Recipe: Mapped Type Expression Is Not Supported
1859
1860**Rule:** `arkts-no-mapped-types`
1861
1862**Severity: error**
1863
1864ArkTS does not support mapped types. Use other language idioms and regular classes to achieve the same behaviour.
1865
1866**TypeScript**
1867
1868```typescript
1869type OptionsFlags<Type> = {
1870  [Property in keyof Type]: boolean
1871}
1872```
1873
1874**ArkTS**
1875
1876```typescript
1877class C {
1878  n: number = 0
1879  s: string = ''
1880}
1881
1882class CFlags {
1883  n: boolean = false
1884  s: boolean = false
1885}
1886```
1887
1888### Recipe: `with` Statement Is Not Supported
1889
1890**Rule:** `arkts-no-with`
1891
1892**Severity: error**
1893
1894ArkTS does not support the `with` statement. Use other language idioms to achieve the same behaviour.
1895
1896**TypeScript**
1897
1898```typescript
1899with (Math) { // Compile-time error, but JavaScript code can still be emitted.
1900  let r: number = 42;
1901  let area: number = PI * r * r;
1902}
1903```
1904
1905**ArkTS**
1906
1907```typescript
1908let r: number = 42;
1909let area: number = Math.PI * r * r;
1910```
1911
1912### Recipe: `throw` Statements Do Not Accept Values of Arbitrary Types
1913
1914**Rule:** `arkts-limited-throw`
1915
1916**Severity: error**
1917
1918ArkTS supports throwing only objects of the class `Error` or any
1919derived class. Throwing an arbitrary type (for example, a `number` or `string`)
1920is prohibited.
1921
1922**TypeScript**
1923
1924```typescript
1925throw 4
1926throw ''
1927throw new Error()
1928```
1929
1930**ArkTS**
1931
1932```typescript
1933throw new Error()
1934```
1935
1936### Recipe: Function Return Type Inference Is Limited
1937
1938**Rule:** `arkts-no-implicit-return-types`
1939
1940**Severity: error**
1941
1942ArkTS supports type inference for function return types, but this functionality
1943is currently restricted. In particular, when the expression in the `return`
1944statement is a call to a function or method whose return value type is omitted,
1945a compile-time error occurs. If this is the case, specify the return type explicitly.
1946
1947**TypeScript**
1948
1949```typescript
1950// Compile-time error when noImplicitAny is enabled.
1951function f(x: number) {
1952  if (x <= 0) {
1953    return x;
1954  }
1955  return g(x);
1956}
1957
1958// Compile-time error when noImplicitAny is enabled.
1959function g(x: number) {
1960  return f(x - 1);
1961}
1962
1963function doOperation(x: number, y: number) {
1964  return x + y;
1965}
1966
1967f(10);
1968doOperation(2, 3);
1969```
1970
1971**ArkTS**
1972
1973```typescript
1974// An explicit return type is required.
1975function f(x: number): number {
1976  if (x <= 0) {
1977    return x;
1978  }
1979  return g(x);
1980}
1981
1982// Return type may be omitted. It is inferred from f's explicit type.
1983function g(x: number): number {
1984  return f(x - 1);
1985}
1986
1987// In this case, the return type will be inferred.
1988function doOperation(x: number, y: number) {
1989  return x + y;
1990}
1991
1992f(10);
1993doOperation(2, 3);
1994```
1995
1996### Recipe: Destructuring Parameter Declarations Are Not Supported
1997
1998**Rule:** `arkts-no-destruct-params`
1999
2000**Severity: error**
2001
2002ArkTS requires parameters to be passed directly to the function, and local names to be assigned manually.
2003
2004**TypeScript**
2005
2006```typescript
2007function drawText({ text = '', location: [x, y] = [0, 0], bold = false }) {
2008  text;
2009  x;
2010  y;
2011  bold;
2012}
2013
2014drawText({ text: 'Hello, world!', location: [100, 50], bold: true })
2015```
2016
2017**ArkTS**
2018
2019```typescript
2020function drawText(text: String, location: number[], bold: boolean) {
2021  let x = location[0];
2022  let y = location[1];
2023  text;
2024  x;
2025  y;
2026  bold;
2027}
2028
2029function main() {
2030  drawText('Hello, world!', [100, 50], true);
2031}
2032```
2033
2034### Recipe: Nested Functions Are Not Supported
2035
2036**Rule:** `arkts-no-nested-funcs`
2037
2038**Severity: error**
2039
2040ArkTS does not support nested functions. Use lambdas instead.
2041
2042**TypeScript**
2043
2044```typescript
2045function addNum(a: number, b: number): void {
2046
2047    // Nested function
2048  function logToConsole(message: string): void {
2049    console.log(message)
2050  }
2051
2052  let result = a + b
2053
2054    // Invoke the nested function.
2055  logToConsole('result is ' + result)
2056}
2057```
2058
2059**ArkTS**
2060
2061```typescript
2062function addNum(a: number, b: number): void {
2063    // Use lambda instead of a nested function.
2064  let logToConsole: (message: string) => void = (message: string): void => {
2065    console.log(message)
2066  }
2067
2068  let result = a + b
2069
2070  logToConsole('result is ' + result)
2071}
2072```
2073
2074### Recipe: Using `this` Inside Stand-Alone Functions Is Not Supported
2075
2076**Rule:** `arkts-no-standalone-this`
2077
2078**Severity: error**
2079
2080ArkTS does not support the usage of `this` inside stand-alone functions and inside static methods. `this` can be used in instance methods only.
2081
2082**TypeScript**
2083
2084```typescript
2085function foo(i: string) {
2086    this.count = i // Compile-time error only when noImplicitThis is enabled.
2087}
2088
2089class A {
2090  count: string = 'a'
2091  m = foo
2092}
2093
2094let a = new A();
2095console.log(a.count); // Prints "a".
2096a.m(b);
2097console.log(a.count); // Prints "b".
2098```
2099
2100**ArkTS**
2101
2102```typescript
2103class A {
2104  count: string = 'a'
2105  m(i: string): void {
2106    this.count = i;
2107  }
2108}
2109
2110function main(): void {
2111  let a = new A();
2112  console.log(a.count);  // Prints "a".
2113  a.m('b');
2114  console.log(a.count);  // Prints "b".
2115}
2116```
2117
2118### Recipe: Generator Functions Are Not Supported
2119
2120**Rule:** `arkts-no-generators`
2121
2122**Severity: error**
2123
2124Currently, ArkTS does not support generator functions. Use the `async`/`await` mechanism for multitasking.
2125
2126**TypeScript**
2127
2128```typescript
2129function* counter(start: number, end: number) {
2130  for (let i = start; i <= end; i++) {
2131    yield i
2132  }
2133}
2134
2135for (let num of counter(1, 5)) {
2136  console.log(num)
2137}
2138```
2139
2140**ArkTS**
2141
2142```typescript
2143async function complexNumberProcessing(num: number): Promise<number> {
2144  // ...
2145  return num;
2146}
2147
2148async function foo() {
2149  for (let i = 1; i <= 5; i++) {
2150    await complexNumberProcessing(i);
2151  }
2152}
2153
2154foo()
2155```
2156
2157### Recipe: Type Guarding Is Supported with `instanceof` and `as`
2158
2159**Rule:** `arkts-no-is`
2160
2161**Severity: error**
2162
2163ArkTS does not support the `is` operator, which must be replaced by the
2164`instanceof` operator. Note that the fields of an object must be cast to the
2165appropriate type with the `as` operator before being used.
2166
2167**TypeScript**
2168
2169```typescript
2170class Foo {
2171  foo: string = ''
2172  common: string = ''
2173}
2174
2175class Bar {
2176  bar: string = ''
2177  common: string = ''
2178}
2179
2180function isFoo(arg: any): arg is Foo {
2181  return arg.foo !== undefined
2182}
2183
2184function doStuff(arg: Foo | Bar) {
2185  if (isFoo(arg)) {
2186    console.log(arg.foo)  // OK
2187    console.log(arg.bar)  // Compile-time error
2188  } else {
2189    console.log(arg.foo)  // Compile-time error
2190    console.log(arg.bar)  // OK
2191  }
2192}
2193
2194doStuff({ foo: 123, common: '123' })
2195doStuff({ bar: 123, common: '123' })
2196```
2197
2198**ArkTS**
2199
2200```typescript
2201class Foo {
2202  foo: string = ''
2203  common: string = ''
2204}
2205
2206class Bar {
2207  bar: string = ''
2208  common: string = ''
2209}
2210
2211function isFoo(arg: Object): boolean {
2212  return arg instanceof Foo
2213}
2214
2215function doStuff(arg: Object): void {
2216  if (isFoo(arg)) {
2217    let fooArg = arg as Foo
2218    console.log(fooArg.foo)   // OK
2219    console.log(arg.bar)    // Compile-time error
2220  } else {
2221    let barArg = arg as Bar
2222    console.log(arg.foo)    // Compile-time error
2223    console.log(barArg.bar)   // OK
2224  }
2225}
2226
2227function main(): void {
2228  doStuff(new Foo())
2229  doStuff(new Bar())
2230}
2231```
2232
2233### Recipe: It is possible to spread only arrays or classes derived from arrays into the rest parameter or array literals
2234
2235**Rule:** `arkts-no-spread`
2236
2237**Severity: error**
2238
2239The only supported scenario for the spread operator is to spread an array or
2240class derived from array into the rest parameter or array literal.
2241Otherwise, manually "unpack" data from arrays and objects, where necessary.
2242All typed arrays from the standard library (for example, ``Int32Array``)
2243are also supported.
2244
2245**TypeScript**
2246
2247```typescript
2248function foo(x: number, y: number, z: number) {
2249  // ...
2250}
2251
2252let args: [number, number, number] = [0, 1, 2];
2253foo(...args);
2254```
2255
2256**ArkTS**
2257
2258```typescript
2259function log_numbers(x: number, y: number, z: number) {
2260  // ...
2261}
2262
2263let numbers: number[] = [1, 2, 3];
2264log_numbers(numbers[0], numbers[1], numbers[2]);
2265```
2266
2267**TypeScript**
2268
2269```typescript
2270let point2d = { x: 1, y: 2 };
2271let point3d = { ...point2d, z: 3 };
2272```
2273
2274**ArkTS**
2275
2276```typescript
2277class Point2D {
2278  x: number = 0; y: number = 0
2279}
2280
2281class Point3D {
2282  x: number = 0; y: number = 0; z: number = 0
2283  constructor(p2d: Point2D, z: number) {
2284    this.x = p2d.x;
2285    this.y = p2d.y;
2286    this.z = z;
2287  }
2288}
2289
2290let p3d = new Point3D({ x: 1, y: 2 } as Point2D, 3);
2291
2292class DerivedFromArray extends Uint16Array {};
2293
2294let arr1 = [1, 2, 3];
2295let arr2 = new Uint16Array([4, 5, 6]);
2296let arr3 = new DerivedFromArray([7, 8, 9]);
2297let arr4 = [...arr1, 10, ...arr2, 11, ...arr3];
2298```
2299
2300### Recipe: Interface Cannot Extend Interfaces with the Same Method
2301
2302**Rule:** `arkts-no-extend-same-prop`
2303
2304**Severity: error**
2305
2306In TypeScript, an interface that extends two other interfaces with the same method
2307must declare that method with a combined return type. It is not allowed in
2308ArkTS because ArkTS does not allow an interface to contain two methods with
2309signatures that are not distinguishable, for example, two methods that have the same
2310parameter lists but different return types.
2311
2312**TypeScript**
2313
2314```typescript
2315interface Mover {
2316  getStatus(): { speed: number }
2317}
2318interface Shaker {
2319  getStatus(): { frequency: number }
2320}
2321
2322interface MoverShaker extends Mover, Shaker {
2323  getStatus(): {
2324    speed: number
2325    frequency: number
2326  }
2327}
2328
2329class C implements MoverShaker {
2330  private speed: number = 0
2331  private frequency: number = 0
2332
2333  getStatus() {
2334    return { speed: this.speed, frequency: this.frequency }
2335  }
2336}
2337```
2338
2339**ArkTS**
2340
2341```typescript
2342class MoveStatus {
2343  public speed: number
2344  constructor() {
2345    this.speed = 0
2346  }
2347}
2348interface Mover {
2349  getMoveStatus(): MoveStatus
2350}
2351
2352class ShakeStatus {
2353  public frequency: number
2354  constructor() {
2355    this.frequency = 0
2356  }
2357}
2358interface Shaker {
2359  getShakeStatus(): ShakeStatus
2360}
2361
2362class MoveAndShakeStatus {
2363  public speed: number
2364  public frequency: number
2365  constructor() {
2366    this.speed = 0
2367    this.frequency = 0
2368  }
2369}
2370
2371class C implements Mover, Shaker {
2372  private move_status: MoveStatus
2373  private shake_status: ShakeStatus
2374
2375  constructor() {
2376    this.move_status = new MoveStatus()
2377    this.shake_status = new ShakeStatus()
2378  }
2379
2380  public getMoveStatus(): MoveStatus {
2381    return this.move_status
2382  }
2383
2384  public getShakeStatus(): ShakeStatus {
2385    return this.shake_status
2386  }
2387
2388  public getStatus(): MoveAndShakeStatus {
2389    return {
2390      speed: this.move_status.speed,
2391      frequency: this.shake_status.frequency
2392    }
2393  }
2394}
2395```
2396
2397### Recipe: Declaration Merging Is Not Supported
2398
2399**Rule:** `arkts-no-decl-merging`
2400
2401**Severity: error**
2402
2403ArkTS does not support merging declarations. Keep all definitions of classes and interfaces compact in the codebase.
2404
2405**TypeScript**
2406
2407```typescript
2408interface Document {
2409  createElement(tagName: any): Element
2410}
2411
2412interface Document {
2413  createElement(tagName: string): HTMLElement
2414}
2415
2416interface Document {
2417  createElement(tagName: number): HTMLDivElement
2418  createElement(tagName: boolean): HTMLSpanElement
2419  createElement(tagName: string, value: number): HTMLCanvasElement
2420}
2421```
2422
2423**ArkTS**
2424
2425```typescript
2426interface Document {
2427  createElement(tagName: number): HTMLDivElement
2428  createElement(tagName: boolean): HTMLSpanElement
2429  createElement(tagName: string, value: number): HTMLCanvasElement
2430  createElement(tagName: string): HTMLElement
2431  createElement(tagName: Object): Element
2432}
2433```
2434
2435### Recipe: Interfaces Cannot Extend Classes
2436
2437**Rule:** `arkts-extends-only-class`
2438
2439**Severity: error**
2440
2441ArkTS does not support interfaces that extend classes. Interfaces can extend only interfaces.
2442
2443**TypeScript**
2444
2445```typescript
2446class Control {
2447  state: number = 0
2448}
2449
2450interface SelectableControl extends Control {
2451  select(): void
2452}
2453```
2454
2455**ArkTS**
2456
2457```typescript
2458interface Control {
2459  state: number
2460}
2461
2462interface SelectableControl extends Control {
2463  select(): void
2464}
2465```
2466
2467### Recipe: Constructor Function Type Is Not Supported
2468
2469**Rule:** `arkts-no-ctor-signatures-funcs`
2470
2471**Severity: error**
2472
2473ArkTS does not support the usage of the constructor function type. Use lambdas instead.
2474
2475**TypeScript**
2476
2477```typescript
2478class Person {
2479  constructor(
2480    name: string,
2481    age: number
2482  ) {}
2483}
2484type PersonCtor = new (name: string, age: number) => Person
2485
2486function createPerson(Ctor: PersonCtor, name: string, age: number): Person
2487{
2488  return new Ctor(name, age)
2489}
2490
2491const person = createPerson(Person, 'John', 30)
2492```
2493
2494**ArkTS**
2495
2496```typescript
2497class Person {
2498  constructor(
2499    name: string,
2500    age: number
2501  ) {}
2502}
2503type PersonCtor = (n: string, a: number) => Person
2504
2505function createPerson(Ctor: PersonCtor, n: string, a: number): Person {
2506  return Ctor(n, a)
2507}
2508
2509let Impersonizer: PersonCtor = (n: string, a: number): Person => {
2510  return new Person(n, a)
2511}
2512
2513const person = createPerson(Impersonizer, 'John', 30)
2514```
2515
2516### Recipe: Enumeration Members Can Be Initialized Only with Compile Time Expressions of the Same Type
2517
2518**Rule:** `arkts-no-enum-mixed-types`
2519
2520**Severity: error**
2521
2522ArkTS does not support initializing members of enumerations with expressions
2523that are evaluated during program runtime. Besides, all explicitly set
2524initializers must be of the same type.
2525
2526**TypeScript**
2527
2528```typescript
2529enum E1 {
2530  A = 0xa,
2531  B = 0xb,
2532  C = Math.random(),
2533  D = 0xd,
2534  E // 0xe inferred
2535}
2536
2537enum E2 {
2538  A = 0xa,
2539  B = '0xb',
2540  C = 0xc,
2541  D = '0xd'
2542}
2543```
2544
2545**ArkTS**
2546
2547```typescript
2548enum E1 {
2549  A = 0xa,
2550  B = 0xb,
2551  C = 0xc,
2552  D = 0xd,
2553  E // 0xe inferred
2554}
2555
2556enum E2 {
2557  A = '0xa',
2558  B = '0xb',
2559  C = '0xc',
2560  D = '0xd'
2561}
2562```
2563
2564### Recipe: `enum` Declaration Merging Is Not Supported
2565
2566**Rule:** `arkts-no-enum-merging`
2567
2568**Severity: error**
2569
2570ArkTS does not support merging declarations for `enum`. Keep the declaration of each `enum` compact in the codebase.
2571
2572**TypeScript**
2573
2574```typescript
2575enum ColorSet {
2576  RED,
2577  GREEN
2578}
2579enum ColorSet {
2580  YELLOW = 2
2581}
2582enum ColorSet {
2583  BLACK = 3,
2584  BLUE
2585}
2586```
2587
2588**ArkTS**
2589
2590```typescript
2591enum ColorSet {
2592  RED,
2593  GREEN,
2594  YELLOW,
2595  BLACK,
2596  BLUE
2597}
2598```
2599
2600### Recipe: Namespaces Cannot Be Used as Objects
2601
2602**Rule:** `arkts-no-ns-as-obj`
2603
2604**Severity: error**
2605
2606ArkTS does not support the usage of namespaces as objects. Classes or modules can be interpreted as analogs of namespaces.
2607
2608**TypeScript**
2609
2610```typescript
2611namespace MyNamespace {
2612  export let x: number
2613}
2614
2615let m = MyNamespace
2616m.x = 2
2617```
2618
2619**ArkTS**
2620
2621```typescript
2622namespace MyNamespace {
2623  export let x: number
2624}
2625
2626MyNamespace.x = 2
2627```
2628
2629### Recipe: Non-declaration Statements in Namespaces Are Not Supported
2630
2631**Rule:** `arkts-no-ns-statements`
2632
2633**Severity: error**
2634
2635ArkTS does not support statements in namespaces. Use a function to execute statements.
2636
2637**TypeScript**
2638
2639```typescript
2640namespace A {
2641  export let x: number
2642  x = 1
2643}
2644```
2645
2646**ArkTS**
2647
2648```typescript
2649namespace A {
2650  export let x: number
2651
2652  export function init() {
2653    x = 1
2654  }
2655}
2656
2657// Initialization function should be called to execute statements.
2658A.init()
2659```
2660
2661### Recipe: `require` and `import` Assignment Are Not Supported
2662
2663**Rule:** `arkts-no-require`
2664
2665**Severity: error**
2666
2667ArkTS does not support importing via `require`.
2668It does not support `import` assignments either.
2669Use the regular `import` syntax  instead.
2670
2671**TypeScript**
2672
2673```typescript
2674import m = require('mod')
2675```
2676
2677**ArkTS**
2678
2679```typescript
2680import * as m from 'mod'
2681```
2682
2683### Recipe: `export = ...` Is Not Supported
2684
2685**Rule:** `arkts-no-export-assignment`
2686
2687**Severity: error**
2688
2689ArkTS does not support the `export = ...` syntax.
2690Use the ordinary `export` and `import` syntaxes instead.
2691
2692**TypeScript**
2693
2694```typescript
2695// module1
2696export = Point
2697
2698class Point {
2699  constructor(x: number, y: number) {}
2700  static origin = new Point(0, 0)
2701}
2702
2703// module2
2704import Pt = require('module1')
2705
2706let p = Pt.Point.origin
2707```
2708
2709**ArkTS**
2710
2711```typescript
2712// module1
2713export class Point {
2714  constructor(x: number, y: number) {}
2715  static origin = new Point(0, 0)
2716}
2717
2718// module2
2719import * as Pt from 'module1'
2720
2721let p = Pt.Point.origin
2722```
2723
2724### Recipe: Ambient Module Declaration Is Not Supported
2725
2726**Rule:** `arkts-no-ambient-decls`
2727
2728**Severity: error**
2729
2730ArkTS does not support ambient module declaration because it has its own mechanisms for interoperating with JavaScript.
2731
2732**TypeScript**
2733
2734```typescript
2735declare module 'someModule' {
2736  export function normalize(s: string): string;
2737}
2738```
2739
2740**ArkTS**
2741
2742```typescript
2743// Import what you need from the original module.
2744import { normalize } from "someModule"
2745```
2746
2747### Recipe: Wildcards in Module Names Are Not Supported
2748
2749**Rule:** `arkts-no-module-wildcards`
2750
2751**Severity: error**
2752
2753ArkTS does not support wildcards in module names, because import is a compile-time feature in ArkTS, not a runtime feature.
2754Use the ordinary `export` syntax instead.
2755
2756**TypeScript**
2757
2758```typescript
2759// Declaration:
2760declare module '*!text' {
2761  const content: string
2762  export default content
2763}
2764
2765// Consuming code:
2766import fileContent from 'some.txt!text'
2767```
2768
2769**ArkTS**
2770
2771```typescript
2772// Declaration:
2773declare namespace N {
2774  function foo(x: number): number
2775}
2776
2777// Consuming code:
2778import * as m from 'module'
2779console.log('N.foo called: ' + N.foo(42))
2780```
2781
2782### Recipe: UMD Is Not Supported
2783
2784**Rule:** `arkts-no-umd`
2785
2786**Severity: error**
2787
2788ArkTS does not support universal module definitions (UMD), because it does not have the concept of "script" (as opposed to "module").
2789In addition, import is a compile-time feature in ArkTS, not a runtime feature.
2790Use the ordinary `export` and `import` syntaxes instead.
2791
2792**TypeScript**
2793
2794```typescript
2795// math-lib.d.ts
2796export const isPrime(x: number): boolean
2797export as namespace mathLib
2798
2799// In script
2800mathLib.isPrime(2)
2801```
2802
2803**ArkTS**
2804
2805```typescript
2806// math-lib.d.ts
2807namespace mathLib {
2808  export isPrime(x: number): boolean
2809}
2810
2811// In program
2812import { mathLib } from "math-lib"
2813mathLib.isPrime(2)
2814```
2815
2816### Recipe: `new.target` Is Not Supported
2817
2818**Rule:** `arkts-no-new-target`
2819
2820**Severity: error**
2821
2822ArkTS does not support `new.target`, because there is no concept of runtime
2823prototype inheritance in the language. This feature is considered not applicable
2824to static typing.
2825
2826### Recipe: Definite Assignment Assertions Are Not Supported
2827
2828**Rule:** `arkts-no-definite-assignment`
2829
2830**Severity: warning**
2831
2832ArkTS does not support definite assignment assertions `let v!: T` because
2833they are considered an excessive compiler hint.
2834Use declarations with initialization instead.
2835
2836**TypeScript**
2837
2838```typescript
2839let x!: number // Hint: x will be initialized before usage.
2840
2841initialize()
2842
2843function initialize() {
2844  x = 10
2845}
2846
2847console.log('x = ' + x)
2848```
2849
2850**ArkTS**
2851
2852```typescript
2853function initialize(): number {
2854  return 10
2855}
2856
2857let x: number = initialize()
2858
2859console.log('x = ' + x)
2860```
2861
2862### Recipe: Prototype Assignment Is Not Supported
2863
2864**Rule:** `arkts-no-prototype-assignment`
2865
2866**Severity: error**
2867
2868ArkTS does not support prototype assignment because there is no concept of
2869runtime prototype inheritance in the language. This feature is considered not
2870applicable to static typing. Mechanism of classes and/or interfaces must
2871be used instead to statically "combine" methods to data together.
2872
2873**TypeScript**
2874
2875```typescript
2876let C = function(p) {
2877  this.p = p // Compile-time error only when noImplicitThis is enabled
2878}
2879
2880C.prototype = {
2881  m() {
2882    console.log(this.p)
2883  }
2884}
2885
2886C.prototype.q = function(r: string) {
2887  return this.p == r
2888}
2889```
2890
2891**ArkTS**
2892
2893```typescript
2894class C {
2895  p: string = ''
2896  m() {
2897    console.log(this.p)
2898  }
2899  q(r: string) {
2900    return this.p == r
2901  }
2902}
2903```
2904
2905### Recipe: `globalThis` Is Not Supported
2906
2907**Rule:** `arkts-no-globalthis`
2908
2909**Severity: warning**
2910
2911ArkTS does not support both global scope and `globalThis` because untyped
2912objects with dynamically changed layout are not supported.
2913
2914**TypeScript**
2915
2916```typescript
2917// In a global file:
2918var abc = 100
2919
2920// Refers to 'abc' from above.
2921let x = globalThis.abc
2922```
2923
2924**ArkTS**
2925
2926```typescript
2927// File 1
2928export let abc: number = 100
2929
2930// File 2
2931import * as M from 'file1'
2932
2933let x = M.abc
2934```
2935
2936### Recipe: Some Utility Types Are Not Supported
2937
2938**Rule:** `arkts-no-utility-types`
2939
2940**Severity: error**
2941
2942Currently ArkTS does not support utility types from TypeScript extensions to the
2943standard library. Exceptions are `Partial`, `Required`, `Readonly` and `Record`.
2944
2945For the type *Record<K, V>*, the type of an indexing expression *rec[index]* is of the type *V | undefined*.
2946
2947### Recipe: Declaring Properties on Functions Is Not Supported
2948
2949**Rule:** `arkts-no-func-props`
2950
2951**Severity: error**
2952
2953ArkTS does not support declaring properties on functions because there is no
2954support for objects with dynamically changing layout. Function objects follow
2955this rule and their layout cannot be changed at runtime.
2956
2957### Recipe: `Function.apply` and `Function.call` Are Not Supported
2958
2959**Rule:** `arkts-no-func-apply-call`
2960
2961**Severity: error**
2962
2963ArkTS does not support `Function.apply` or `Function.call`. These APIs are needed in the standard
2964library to explicitly set the parameter `this` for the called function.
2965In ArkTS, the semantics of `this` is restricted to the conventional OOP
2966style, and the usage of `this` in stand-alone functions is prohibited.
2967
2968### Recipe:`Function.bind` Is Not Supported
2969
2970**Rule:** `arkts-no-func-bind`
2971
2972**Severity: warning**
2973
2974ArkTS does not support `Function.bind`. These APIs are needed in the standard
2975library to explicitly set the parameter `this` for the called function.
2976In ArkTS, the semantics of `this` is restricted to the conventional OOP
2977style, and the usage of `this` in stand-alone functions is prohibited.
2978
2979### Recipe: `as const` Assertions Are Not Supported
2980
2981**Rule:** `arkts-no-as-const`
2982
2983**Severity: error**
2984
2985ArkTS does not support `as const` assertions, because in standard TypeScript
2986`as const` is used to annotate literals with corresponding literal types, and ArkTS
2987does not support literal types.
2988
2989**TypeScript**
2990
2991```typescript
2992// Type 'hello':
2993let x = 'hello' as const
2994
2995// Type 'readonly [10, 20]':
2996let y = [10, 20] as const
2997
2998// Type '{ readonly text: "hello" }':
2999let z = { text: 'hello' } as const
3000```
3001
3002**ArkTS**
3003
3004```typescript
3005// Type 'string':
3006let x: string = 'hello'
3007
3008// Type 'number[]':
3009let y: number[] = [10, 20]
3010
3011class Label {
3012  text: string = ''
3013}
3014
3015// Type 'Label':
3016let z: Label = {
3017  text: 'hello'
3018}
3019```
3020
3021### Recipe: Import Assertions Are Not Supported
3022
3023**Rule:** `arkts-no-import-assertions`
3024
3025**Severity: error**
3026
3027ArkTS does not support import assertions, because import is a
3028compile-time feature in ArkTS, not a runtime feature. So asserting the correctness of imported APIs
3029in runtime does not make sense for the statically typed language. Use the ordinary
3030`import` syntax instead.
3031
3032**TypeScript**
3033
3034```typescript
3035import { obj } from 'something.json' assert { type: 'json' }
3036```
3037
3038**ArkTS**
3039
3040```typescript
3041// The correctness of importing T will be checked at compile time.
3042import { something } from 'module'
3043```
3044
3045### Recipe: Usage of Standard Libraries Is Restricted
3046
3047**Rule:** `arkts-limited-stdlib`
3048
3049**Severity: error**
3050
3051ArkTS does not support certain APIs in the TypeScript and JavaScript standard libraries.
3052Most of these restricted APIs are used to manipulate objects in a
3053dynamic manner, which is not compatible with static typing. The usage of
3054the following APIs is prohibited:
3055
3056Properties and functions of the global object: `eval`
3057
3058`Object`: `__proto__`, `__defineGetter__`, `__defineSetter__`,
3059`__lookupGetter__`, `__lookupSetter__`, `assign`, `create`,
3060`defineProperties`, `defineProperty`, `freeze`,
3061`fromEntries`, `getOwnPropertyDescriptor`, `getOwnPropertyDescriptors`,
3062`getOwnPropertySymbols`, `getPrototypeOf`,
3063`hasOwnProperty`, `is`, `isExtensible`, `isFrozen`,
3064`isPrototypeOf`, `isSealed`, `preventExtensions`,
3065`propertyIsEnumerable`, `seal`, `setPrototypeOf`
3066
3067`Reflect`: `apply`, `construct`, `defineProperty`, `deleteProperty`,
3068`getOwnPropertyDescriptor`, `getPrototypeOf`,
3069`isExtensible`, `preventExtensions`,
3070`setPrototypeOf`
3071
3072`Proxy`: `handler.apply()`, `handler.construct()`,
3073`handler.defineProperty()`, `handler.deleteProperty()`, `handler.get()`,
3074`handler.getOwnPropertyDescriptor()`, `handler.getPrototypeOf()`,
3075`handler.has()`, `handler.isExtensible()`, `handler.ownKeys()`,
3076`handler.preventExtensions()`, `handler.set()`, `handler.setPrototypeOf()`
3077
3078### Recipe: Strict Type Checking Is Enforced
3079
3080**Rule:** `arkts-strict-typing`
3081
3082**Severity: error**
3083
3084Type checking in ArkTS is not optional. Any code must be explicitly and
3085correctly typed to be compiled and run. When porting code from standard TypeScript,
3086enable the following flags: `noImplicitReturns`, `strictFunctionTypes`,
3087`strictNullChecks`, and `strictPropertyInitialization`.
3088
3089**TypeScript**
3090
3091```typescript
3092// Compile-time error only when noImplicitReturns is enabled.
3093function foo(s: string): string {
3094  if (s != '') {
3095    console.log(s)
3096    return s
3097  } else {
3098    console.log(s)
3099  }
3100}
3101
3102let n: number = null // Compile-time error only when strictNullChecks is enabled.
3103```
3104
3105**ArkTS**
3106
3107```typescript
3108function foo(s: string): string {
3109  console.log(s)
3110  return s
3111}
3112
3113let n1: number | null = null
3114let n2: number = 0
3115```
3116
3117If you cannot initialize an instance property by declaration or in a constructor when defining a class, you can use the definite assignment assertion operator (!) to clear the `strictPropertyInitialization` error.
3118
3119However, the use of the definite assignment assertion operator (!) increases the risk of code errors. Therefore, you must ensure that the instance property has been assigned a value before being used. Otherwise, the runtime exceptions may occur.
3120
3121In addition, the use of the definite assignment assertion operator (!) requires a runtime type check, resulting in additional runtime overhead. It also generates the error `warning: arkts-no-definite-assignment` at the compile time. Therefore, use it only when quite necessary.
3122
3123**TypeScript**
3124
3125```typescript
3126class C {
3127  name: string  // ֻCompile-time error only when strictPropertyInitialization is enabled.
3128  age: number   // ֻCompile-time error only when strictPropertyInitialization is enabled.
3129}
3130
3131let c = new C()
3132```
3133
3134**ArkTS**
3135
3136```typescript
3137class C {
3138  name: string = ''
3139  age!: number      // warning: arkts-no-definite-assignment
3140
3141  initAge(age: number) {
3142    this.age = age
3143  }
3144}
3145
3146let c = new C()
3147c.initAge(10)
3148```
3149
3150### Recipe: Disabling Type Checking with In-Place Comments Is Not Allowed
3151
3152**Rule:** `arkts-strict-typing-required`
3153
3154**Severity: error**
3155
3156Type checking in ArkTS is not optional. Any code must be explicitly and
3157correctly typed to be compiled and run. Disabling type checking in-place
3158with special comments is not allowed. In particular, `@ts-ignore` and
3159`@ts-nocheck` annotations are not supported.
3160
3161**TypeScript**
3162
3163```typescript
3164// @ts-nocheck
3165// ...
3166// Some code with type checking disabled.
3167// ...
3168
3169let s1: string = null // No error, since type checking is disabled.
3170
3171// @ts-ignore
3172let s2: string = null // No error, since type checking is disabled.
3173```
3174
3175**ArkTS**
3176
3177```typescript
3178let s1: string | null = null // No error. The types are proper.
3179let s2: string = null // Compile-time error.
3180```
3181
3182### Recipe: No Dependencies on TypeScript Code Are Allowed
3183
3184**Rule:** `arkts-no-ts-deps`
3185
3186**Severity: error**
3187
3188Currently, the codebase implemented in the standard TypeScript language must not
3189depend on ArkTS by importing an ArkTS codebase. Imports in the reverse
3190direction are supported.
3191
3192**TypeScript**
3193
3194```typescript
3195// app.ets
3196export class C {
3197  // ...
3198}
3199
3200// lib.ts
3201import { C } from 'app'
3202```
3203
3204**ArkTS**
3205
3206```typescript
3207// lib1.ets
3208export class C {
3209  // ...
3210}
3211
3212// lib2.ets
3213import { C } from 'lib1'
3214```
3215
3216### Recipe: Classes Cannot Be Used as Objects
3217
3218**Rule:** `arkts-no-classes-as-obj`
3219
3220**Severity: warning**
3221
3222ArkTS does not support using classes as objects (assigning them to variables,
3223etc.). This is because in ArkTS, a `class` declaration introduces a new type,
3224not a value.
3225
3226### Recipe: `import` Statements After Other Statements Are Not Allowed
3227
3228**Rule:** `arkts-no-misplaced-imports`
3229
3230**Severity: error**
3231
3232In ArkTS, all `import` statements should go before all other statements in the program.
3233
3234**TypeScript**
3235
3236```typescript
3237class C {
3238  s: string = ''
3239  n: number = 0
3240}
3241
3242import foo from 'module1'
3243```
3244
3245**ArkTS**
3246
3247```typescript
3248import foo from 'module1'
3249
3250class C {
3251  s: string = ''
3252  n: number = 0
3253}
3254```
3255
3256### Recipe: Usage of `ESObject` Type Is Restricted
3257
3258**Rule:** `arkts-limited-esobj`
3259
3260**Severity: warning**
3261
3262ArkTS does not allow using `ESObject` type in some cases. The most part of
3263limitations are put in place in order to prevent spread of dynamic objects in
3264the static codebase. The only scenario where it is permited to use `ESObject`
3265as type specifier is in local variable declaration. Initialization of variables
3266with `ESObject` type is also limited. Such variables can only be initialized
3267with values that originate from interop: other `ESObject` typed variables,
3268any, unknown, variables with anonymous type, etc. It is prohibited to
3269initialize `ESObject` typed variable with statically typed value. Varaible
3270of type `ESObject` can only be passed to interop calls and assigned to other
3271variables of type `ESObject`.
3272
3273**ArkTS**
3274
3275```typescript
3276// lib.d.ts
3277declare function foo(): any;
3278declare function bar(a: any): number;
3279
3280// main.ets
3281let e0: ESObject = foo(); // Compile-time error: 'ESObject' typed variable can only be local
3282
3283function f() {
3284  let e1 = foo();        // Compile-time error: type of e1 is 'any'
3285  let e2: ESObject = 1;  // Compile-time error: can't initialize 'ESObject' with not dynamic values
3286  let e3: ESObject = {}; // Compile-time error: can't initialize 'ESObject' with not dynamic values
3287  let e4: ESObject = []; // Compile-time error: can't initialize 'ESObject' with not dynamic values
3288  let e5: ESObject = ""; // Compile-time error: can't initialize 'ESObject' with not dynamic values
3289  e5['prop']             // Compile-time error: can't access dynamic properties of 'ESObject'
3290  e5[1]                  // Compile-time error: can't access dynamic properties of 'ESObject'
3291  e5.prop                // Compile-time error: can't access dynamic properties of 'ESObject'
3292
3293  let e6: ESObject = foo(); // OK - explicitly annotated as 'ESObject'
3294  let e7 = e6;              // OK - initialize 'ESObject' with 'ESObject'
3295  bar(e7)                   // OK - 'ESObject' is passed to interop call
3296}
3297```
3298