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