diff --git a/en/application-dev/quick-start/typescript-to-arkts-migration-guide.md b/en/application-dev/quick-start/typescript-to-arkts-migration-guide.md index 29865c79c490f4ad1678034e001b71e1011f1ab3..627a84e3125a9659a90ab945f8f1ecca0b6d15cb 100644 --- a/en/application-dev/quick-start/typescript-to-arkts-migration-guide.md +++ b/en/application-dev/quick-start/typescript-to-arkts-migration-guide.md @@ -19,7 +19,7 @@ categories: PageBreak -# How to Use The Cookbook +# How to Use the Cookbook The main goal of this cookbook is to provide recipes for all partially supported features and explicitly list all unsupported features. @@ -215,19 +215,15 @@ strong positive impact on performance at the cost of low-effort refactoring. ## Semantics of Operators Is Restricted To achieve better performance and encourage developers write clearer code, -ArkTS restricts the semantics of some operators. A couple of examples are -given below, and the full list of restrictions is outlined in [Recipes](#recipes). +ArkTS restricts the semantics of some operators. An example is given below, +and the full list of restrictions is outlined in [Recipes](#recipes). ### Example ```typescript -// Operator `+` is defined for numbers and strings, but not for other types: -class C { - // ... -} -let c1 : C = new C() -let c2 : C = new C() -console.log(c1 + c2) // Compile-time error +// Unary `+` is defined only for numbers, but not for strings: +console.log(+42) // OK +console.log(+"42") // Compile-time error ``` ### Rationale and Impact @@ -358,12 +354,11 @@ console.log(z.get(2)) **See also** * Recipe: Symbol() API is not supported -* Recipe: Attempt to access an undefined property is a compile-time error +* Recipe: Indexed access is not supported for fields * Recipe: delete operator is not supported * Recipe: typeof operator is allowed only in expression contexts * Recipe: in operator is not supported * Recipe: Property-based runtime type checks are not supported -* Recipe: Dynamic property declaration is not supported * Recipe: Usage of standard library is restricted ## Recipe: `Symbol()` API is not supported @@ -378,6 +373,9 @@ because its most popular use cases make no sense in the statically typed environment. In particular, the object layout is defined at compile time, and cannot be changed at runtime. +`Symbol.iterator` and iterable interfaces are not supported either. +Use arrays and library-level containers to iterate over data. + **TypeScript** ```typescript @@ -385,6 +383,26 @@ const sym = Symbol() let o = { [sym]: "value" } + +let obj = { + data: ['a', 'b', 'c'], + [Symbol.iterator]() { + const this_ = this + let index = 0 + return { + next() { + return { + done: index >= this_.data.length, + value: 'name_' + this_.data[index++] + } + } + } + } +} + +for (let t of obj) { + console.log(t) +} ``` **ArkTS** @@ -394,17 +412,21 @@ class SomeClass { public someProperty : string = "" } let o = new SomeClass() + +let arr:string[] = ['a', 'b', 'c'] +for (let t of arr) { + console.log('name_' + t) +} ``` **See also** * Recipe: Objects with property names that are not identifiers are not supported -* Recipe: Attempt to access an undefined property is a compile-time error +* Recipe: Indexed access is not supported for fields * Recipe: delete operator is not supported * Recipe: typeof operator is allowed only in expression contexts * Recipe: in operator is not supported * Recipe: Property-based runtime type checks are not supported -* Recipe: Dynamic property declaration is not supported * Recipe: Usage of standard library is restricted ## Recipe: Private ‘#’ identifiers are not supported @@ -420,7 +442,7 @@ the keyword `private` instead. ```typescript /* - * Such notation for private fields is not supported: + * Such notation for private fields is not supported in ArkTS: class C { #foo: number = 42 } @@ -435,14 +457,14 @@ class C { } ``` -## Recipe: Use unique names for types, namespaces, etc. +## Recipe: Use unique names for types and namespaces. **Rule `arkts-unique-names`** **Severity: error** -Names for types, namespaces and so on must be unique and distinct from other -names, e.g., variable names. +Names for all types (classes, interfaces, enums) and namespaces must be unique +and distinct from other names, e.g., variable names and function names. **TypeScript** @@ -666,7 +688,7 @@ function fn(s: string): SomeObject { **Severity: error** -ArkTS does not allow having sevaral static blocks for class initialization. +ArkTS does not allow having several static blocks for class initialization. Combine static block statements into one static block. **TypeScript** @@ -780,7 +802,7 @@ interface Employee extends Identity, Contact {} **Severity: error** ArkTS does not support type notation using the `this` keyword (for example, -specifying a method's return type `this` is not allowed). Use explicit type +specifying a method’s return type `this` is not allowed). Use explicit type instead. **TypeScript** @@ -836,7 +858,7 @@ type Y = T extends Array ? Item : never **ArkTS** ```typescript -// Provide explicit contraints within type alias +// Provide explicit constraints within type alias type X1 = T // Rewrite with Object. Less type control, need more type checks for safety @@ -960,100 +982,103 @@ type N = number **Severity: error** -ArkTS does not support indexed access for class fields. Use dot notation -instead. An exception are all typed arrays from the standard library +ArkTS does not support dynamic field declaration and access. Declare all +object fields immediately in the class. Access only those class fields +that are either declared in the class, or accessible via inheritance. Accessing +any other fields is prohibited, and causes compile-time errors. + +To access a field, use `obj.field` syntax, indexed access (`obj["field"]`) +is not supported. An exception are all typed arrays from the standard library (for example, `Int32Array`), which support access to their elements through `container[index]` syntax. **TypeScript** ```typescript -class Point {x: number = 0; y: number = 0} +class Point { + x: number = 0 + y: number = 0 +} let p: Point = {x: 1, y: 2} -let x = p["x"] +console.log(p["x"]) + +class Person { + name: string = "" + age: number = 0; // semicolon is required here + [key: string]: string | number +} + +let person: Person = { + name: "John", + age: 30, + email: "***@example.com", + phoneNumber: "18*********", +} ``` **ArkTS** ```typescript -class Point {x: number = 0; y: number = 0} +class Point { + x: number = 0 + y: number = 0 +} let p: Point = {x: 1, y: 2} -let x = p.x +console.log(p.x) + +class Person { + name: string + age: number + email: string + phoneNumber: string + + constructor(name: string, age: number, email: string, + phoneNumber: string) { + this.name = name + this.age = age + this.email = email + this.phoneNumber = phoneNumber + } +} + +let person = new Person("John", 30, "***@example.com", "18*********") +console.log(person["name"]) // Compile-time error +console.log(person.unknownProperty) // Compile-time error let arr = new Int32Array(1) console.log(arr[0]) ``` -## Recipe: Structural identity is not supported +## Recipe: Structural typing is not supported -**Rule `arkts-no-structural-identity`** +**Rule `arkts-no-structural-typing`** **Severity: error** -Currently, ArkTS does not support structural identity, i.e., the compiler +Currently, ArkTS does not support structural typing, i.e., the compiler cannot compare public APIs of two types and decide whether such types are identical. Use other mechanisms (inheritance, interfaces or type aliases) instead. -In the examples below, types `X` and `Y` are equivalent (interchangeble) -in TypeScript, while in ArkTS they are not. - **TypeScript** ```typescript -interface X { - f(): string -} - -interface Y { // Y is equal to X +interface I1 { f(): string } -``` - -**ArkTS** -```typescript -interface X { +interface I2 { // I2 is structurally equivalent to I1 f(): string } -type Y = X // Y is equal to X -``` - -**See also** - -* Recipe: Structural typing is not supported for subtyping / supertyping -* Recipe: Structural typing is not supported for assignability checks -* Recipe: Structural typing is not supported for type inference - -## Recipe: Structural typing is not supported for subtyping / supertyping - -**Rule `arkts-no-structural-subtyping`** - -**Severity: error** - -Currently, ArkTS does not check structural equivalence for type inference, -i.e., the compiler cannot compare public APIs of two types and decide whether -such types are identical. Use other mechanisms (inheritance or interfaces) -instead. - -**TypeScript** - -```typescript class X { - public foo: number - - constructor() { - this.foo = 0 - } + n: number = 0 + s: string = "" } -class Y { - public foo: number - - constructor() { - this.foo = 0 - } +class Y { // Y is structurally equivalent to X + n: number = 0 + s: string = "" } let x = new X() @@ -1064,104 +1089,62 @@ y = x console.log("Assign Y to X") x = y -``` -**ArkTS** - -```typescript -class X { - public foo: number - - constructor() { - this.foo = 0 - } +function foo(x: X) { + console.log(x.n, x.s) } -// Y is derived from X, which explicitly set subtype / supertype relations: -class Y extends X { - constructor() { - super() - } -} - -let x = new X() -let y = new Y() - -console.log("Assign Y to X") -x = y // ok, X is the super class of Y - -// Cannot assign X to Y -//y = x - compile-time error +// X and Y are equivalent because their public API is equivalent. +// Thus the second call is allowed: +foo(new X()) +foo(new Y()) ``` -**See also** - -* Recipe: Structural identity is not supported -* Recipe: Structural typing is not supported for assignability checks -* Recipe: Structural typing is not supported for type inference - -## Recipe: Structural typing is not supported for assignability checks - -**Rule `arkts-no-structural-assignability`** - -**Severity: error** - -Currently, ArkTS does not check structural equivalence when checking if types -are assignable to each other, i.e., the compiler cannot compare public APIs of -two types and decide whether such types are identical. Use other mechanisms -(inheritance or interfaces) instead. - -**TypeScript** +**ArkTS** ```typescript -class X { - public foo: number +interface I1 { + f(): string +} - constructor() { - this.foo = 0 - } +type I2 = I1 // I2 is an alias for I1 + +class B { + n: number = 0 + s: string = "" } -class Y { - public foo: number +// D is derived from B, which explicitly set subtype / supertype relations: +class D extends B { constructor() { - this.foo = 0 + super() } } -let x = new X() -let y = new Y() - -console.log("Assign X to Y") -y = x +let b = new B() +let d = new D() -console.log("Assign Y to X") -x = y -``` +console.log("Assign D to B") +b = d // ok, B is the superclass of D -**ArkTS** +// An attempt to assign b to d will result in a compile-time error: +// d = b -```typescript interface Z { - foo: number + n: number + s: string } // X implements interface Z, which makes relation between X and Y explicit. class X implements Z { - public foo: number - - constructor() { - this.foo = 0 - } + n: number = 0 + s: string = "" } // Y implements interface Z, which makes relation between X and Y explicit. class Y implements Z { - public foo: number - - constructor() { - this.foo = 0 - } + n: number = 0 + s: string = "" } let x: Z = new X() @@ -1172,13 +1155,15 @@ y = x // ok, both are of the same type console.log("Assign Y to X") x = y // ok, both are of the same type -``` -**See also** +function foo(c: Z): void { + console.log(c.n, c.s) +} -* Recipe: Structural identity is not supported -* Recipe: Structural typing is not supported for subtyping / supertyping -* Recipe: Structural typing is not supported for type inference +// X and Y implement the same interface, thus both calls are allowed: +foo(new X()) +foo(new Y()) +``` ## Recipe: Type inference in case of generic function calls is limited @@ -1223,101 +1208,6 @@ function greet(): T { let z = greet() ``` -## Recipe: Structural typing is not supported for type inference - -**Rule `arkts-no-structural-inference`** - -**Severity: error** - -Currently, ArkTS does not support structural typing, i.e., the compiler cannot -compare public APIs of two types and decide whether such types are identical. -Use inheritance and interfaces to specify the relation between the types -explicitly. - -**TypeScript** - -```typescript -class X { - public foo: number - private s: string - - constructor (f: number) { - this.foo = f - this.s = "" - } - - public say(): void { - console.log("X = ", this.foo) - } -} - -class Y { - public foo: number - - constructor (f: number) { - this.foo = f - } - public say(): void { - console.log("Y = ", this.foo) - } -} - -function bar(z: X): void { - z.say() -} - -// X and Y are equivalent because their public API is equivalent. -// Thus the second call is allowed: -bar(new X(1)) -bar(new Y(2) as X) -``` - -**ArkTS** - -```typescript -interface Z { - say(): void -} - -class X implements Z { - public foo: number - private s: string - - constructor (f: number) { - this.foo = f - this.s = "" - } - public say(): void { - console.log("X = ", this.foo) - } -} - -class Y implements Z { - public foo: number - - constructor (f: number) { - this.foo = f - } - public say(): void { - console.log("Y = ", this.foo) - } -} - -function bar(z: Z): void { - z.say() -} - -// X and Y implement the same interface Z, thus both calls are allowed: -bar(new X(1)) -bar(new Y(2)) -``` - -**See also** - -* Recipe: Structural identity is not supported -* Recipe: Structural typing is not supported for subtyping / supertyping -* Recipe: Structural typing is not supported for assignability checks - ## Recipe: RegExp literals are not supported **Rule `arkts-no-regexp-literals`** @@ -1475,7 +1365,7 @@ id_x_y({x: 5, y: 10}) **See also** * Recipe: Object literals cannot be used as type declarations -* Recipe: Array literals must contain elements of only inferrable types +* Recipe: Array literals must contain elements of only inferable types ## Recipe: Object literals cannot be used as type declarations @@ -1513,17 +1403,17 @@ type S = Set **See also** * Recipe: Object literal must correspond to some explicitly declared class or interface -* Recipe: Array literals must contain elements of only inferrable types +* Recipe: Array literals must contain elements of only inferable types -## Recipe: Array literals must contain elements of only inferrable types +## Recipe: Array literals must contain elements of only inferable types -**Rule `arkts-no-noninferrable-arr-literals`** +**Rule `arkts-no-noninferable-arr-literals`** **Severity: error** Basically, ArkTS infers the type of an array literal as a union type of its contents. However, a compile-time error occurs if there is at least one -element with a non-inferrable type (e.g. untyped object literal). +element with a non-inferable type (e.g. untyped object literal). **TypeScript** @@ -1674,57 +1564,6 @@ class C1 implements C { } ``` -## Recipe: Attempt to access an undefined property is a compile-time error - -**Rule `arkts-no-undefined-prop-access`** - -**Severity: error** - -ArkTS supports accessing only those class properties that are either declared -in the class, or accessible via inheritance. Accessing any other properties is -prohibited, and causes compile-time errors. Use proper types to check property -existence during compilation. - -**TypeScript** - -```typescript -let person = {name: "Bob", isEmployee: true} - -let n = person["name"] -let e = person["isEmployee"] -let s = person["office"] // Compile-time error only with noImplicitAny -``` - -**ArkTS** - -```typescript -class Person { - constructor(name: string, isEmployee: boolean) { - this.name = name - this.isEmployee = isEmployee - } - - name: string - isEmployee: boolean -} - -let person = new Person("Bob", true) -let n = person.name -let e = person.isEmployee -let s = person.office // Compile-time error -``` - -**See also** - -* Recipe: Objects with property names that are not identifiers are not supported -* Recipe: Symbol() API is not supported -* Recipe: delete operator is not supported -* Recipe: typeof operator is allowed only in expression contexts -* Recipe: in operator is not supported -* Recipe: Property-based runtime type checks are not supported -* Recipe: Dynamic property declaration is not supported -* Recipe: Usage of standard library is restricted - ## Recipe: Only `as T` syntax is supported for type casts **Rule `arkts-as-casts`** @@ -1892,11 +1731,10 @@ p.y = null * Recipe: Objects with property names that are not identifiers are not supported * Recipe: Symbol() API is not supported -* Recipe: Attempt to access an undefined property is a compile-time error +* Recipe: Indexed access is not supported for fields * Recipe: typeof operator is allowed only in expression contexts * Recipe: in operator is not supported * Recipe: Property-based runtime type checks are not supported -* Recipe: Dynamic property declaration is not supported ## Recipe: `typeof` operator is allowed only in expression contexts @@ -1933,72 +1771,12 @@ let s2: string * Recipe: Objects with property names that are not identifiers are not supported * Recipe: Symbol() API is not supported -* Recipe: Attempt to access an undefined property is a compile-time error +* Recipe: Indexed access is not supported for fields * Recipe: delete operator is not supported * Recipe: in operator is not supported * Recipe: Property-based runtime type checks are not supported -* Recipe: Dynamic property declaration is not supported * Recipe: Usage of standard library is restricted -## Recipe: Binary `+` operator supports implicit casts only for numbers, enums and strings - -**Rule `arkts-no-polymorphic-plus`** - -**Severity: error** - -If one of the operands of the binary `+` operator is of the string type -(including enum string constant), then the other operand can be of any type, -and its value is implicitly converted to string. -Otherwise, ArkTS supports implicit casts with `+` only for numbers and -numeric enum constants. -ArkTS, like TypeScript, does not support the operator `+` for the booleans. -Elsewhere, any form of an explicit cast is required. - -**TypeScript** - -```typescript -enum E { E1, E2 } - -let a = 10 + 32 // 42 -let b = E.E1 + 10 // 10 -let c = 10 + "5" // "105" - -let d = "5" + E.E2 // "51" -let e = "Hello, " + "world!" // "Hello, world!" -let f = "string" + true // "stringtrue" - -let g = (new Object()) + "string" // "[object Object]string" - -let i = true + true // compile-time error -let j = true + 2 // compile-time error -let k = E.E1 + true // compile-time error -``` - -**ArkTS** - -```typescript -enum E { E1, E2 } - -let a = 10 + 32 // 42 -let b = E.E1 + 10 // 10 -let c = 10 + "5" // "105" - -let d = "5" + E.E2 // "51" -let e = "Hello, " + "world!" // "Hello, world!" -let f = "string" + true // "stringtrue" - -let g = (new Object()).toString() + "string" - - -let i = true + true // compile-time error -let j = true + 2 // compile-time error -let k = E.E1 + true // compile-time error -``` - -**See also** - -* Recipe: Unary operators +, - and ~ work only on numbers - ## Recipe: `instanceof` operator is partially supported **Rule `arkts-instanceof-ref-types`** @@ -2076,11 +1854,10 @@ let b = p instanceof Person // true, and "name" is guaranteed to be present * Recipe: Objects with property names that are not identifiers are not supported * Recipe: Symbol() API is not supported -* Recipe: Attempt to access an undefined property is a compile-time error +* Recipe: Indexed access is not supported for fields * Recipe: delete operator is not supported * Recipe: typeof operator is allowed only in expression contexts * Recipe: Property-based runtime type checks are not supported -* Recipe: Dynamic property declaration is not supported * Recipe: Usage of standard library is restricted ## Recipe: Destructuring assignment is not supported @@ -2200,35 +1977,6 @@ let x = zp.x let y = zp.y ``` -## Recipe: Inference of implied types is not supported - -**Rule `arkts-no-implied-inference`** - -**Severity: error** - -Currently, ArkTS does not support inference of implied types. -Use explicit type notation instead. -Use `Object[]` if you need containers that hold data of mixed types. - -**TypeScript** - -```typescript -let [a, b, c] = [1, "hello", true] -``` - -**ArkTS** - -```typescript -let a = 1 -let b = "hello" -let c = true - -let arr: Object[] = [1, "hello", true] -let a1 = arr[0] -let b1 = arr[1] -let c1 = arr[2] -``` - ## Recipe: Type annotation in catch clause is not supported **Rule `arkts-no-types-in-catch`** @@ -2295,23 +2043,6 @@ for (let i = 0; i < a.length; ++i) { **See also** -* Recipe: Iterable interfaces are not supported -* Recipe: for-of is supported only for arrays and strings - -## Recipe: Iterable interfaces are not supported - -**Rule `arkts-no-iterable`** - -**Severity: error** - -ArkTS does not support the `Symbol` API, `Symbol.iterator` and -eventually iterable interfaces. Use arrays and library-level containers to -iterate over data. - -**See also** - -* Recipe: Symbol() API is not supported -* Recipe: for .. in is not supported * Recipe: for-of is supported only for arrays and strings ## Recipe: `for-of` is supported only for arrays and strings @@ -2346,7 +2077,6 @@ for (let n of numbers) { **See also** * Recipe: for .. in is not supported -* Recipe: Iterable interfaces are not supported ## Recipe: Mapped type expression is not supported @@ -2355,7 +2085,7 @@ for (let n of numbers) { **Severity: error** ArkTS does not support mapped types. Use other language idioms and regular -classes to achieve that same behaviour. +classes to achieve that same behavior. **TypeScript** @@ -2390,7 +2120,7 @@ class CFlags { **Severity: error** ArkTS does not support the `with` statement. Use other language idioms -(including fully qualified names of functions) to achieve that same behaviour. +(including fully qualified names of functions) to achieve that same behavior. **TypeScript** @@ -2408,96 +2138,6 @@ let r: number = 42 console.log("Area: ", Math.PI * r * r) ``` -## Recipe: Values computed at runtime are not supported in `case` statements - -**Rule `arkts-no-computed-case`** - -**Severity: error** - -ArkTS supports `case` statements that contain only compile-time values, -top-level scope `const` values, and `static readonly` class fields. -Use `if` statements as an alternative. - -**TypeScript** - -```typescript -let x = 2 -let y = 3 -switch (x) { - case 1: - console.log(1) - break - case 2: - console.log(2) - break - case y: - console.log(y) - break - default: - console.log("other") -} -``` - -**ArkTS** - -```typescript -let x = 2 -switch (x) { - case 1: - console.log(1) - break - case 2: - console.log(2) - break - case 3: - console.log(3) - break - default: - console.log("other") -} -``` - -## Recipe: `switch` statements cannot accept values of arbitrary types - -**Rule `arkts-limited-switch`** - -**Severity: error** - -ArkTS restricts the types that are supported in `switch` statements. In -particular, values of the types `number`, `Number`, `string`, `String` -or `enum` are supported. Use `if` statements in case of unsupported types. - -**TypeScript** - -```typescript -class Point { - x: number = 0 - y: number = 0 -} - -let a = new Point() - -switch (a) { - case null: break - default: console.log("not null") -} -``` - -**ArkTS** - -```typescript -class Point { - x: number = 0 - y: number = 0 -} - -let a = new Point() - -if (a != null) { - console.log("not null") -} -``` - ## Recipe: `throw` statements cannot accept values of arbitrary types **Rule `arkts-limited-throw`** @@ -2668,8 +2308,8 @@ function addNum(a: number, b: number): void { **Severity: error** -ArkTS does not support the usage of `this` inside stand-alone functions. -`this` can be used in methods only. +ArkTS does not support the usage of `this` inside stand-alone functions and +inside static methods. `this` can be used in instance methods only. **TypeScript** @@ -2738,7 +2378,7 @@ for (let num of counter(1, 5)) { ```typescript async function complexNumberProcessing(n : number) : Promise { - // Some complex logic for proccessing the number here + // Some complex logic for processing the number here return n } @@ -2946,7 +2586,7 @@ let p3d = new Point3D({x: 1, y: 2} as Point2D, 3) console.log(p3d.x, p3d.y, p3d.z) ``` -## Recipe: Interface declarations (extends same property) +## Recipe: Interface can not extend interfaces with the same method **Rule `arkts-no-extend-same-prop`** @@ -3049,8 +2689,8 @@ class C implements Mover, Shaker { **Severity: error** -ArkTS does not support merging declratations. Keep all definitions of classes, -interfaces and so on compact in the codebase. +ArkTS does not support merging declarations. Keep all definitions of classes +and interfaces compact in the codebase. **TypeScript** @@ -3175,11 +2815,10 @@ function main(): void { * Recipe: Objects with property names that are not identifiers are not supported * Recipe: Symbol() API is not supported -* Recipe: Attempt to access an undefined property is a compile-time error +* Recipe: Indexed access is not supported for fields * Recipe: delete operator is not supported * Recipe: typeof operator is allowed only in expression contexts * Recipe: in operator is not supported -* Recipe: Dynamic property declaration is not supported * Recipe: Usage of standard library is restricted ## Recipe: Constructor function type is not supported @@ -3232,67 +2871,6 @@ let Impersonizer: PersonCtor = (n: string, a: number): Person => { const person = createPerson(Impersonizer, "John", 30) ``` -## Recipe: Dynamic property declaration is not supported - -**Rule `arkts-no-dyn-prop-decl`** - -**Severity: error** - -ArkTS does not support dynamic property declaration. Declare all object -properties immediately in the class. While replacement for an array of -objects is possible, it is still better to adhere to the static language -paradigm, and declare fields, their names and types explicitly. - -**TypeScript** - -```typescript -class Person { - name: string = "" - age: number = 0; // semicolon is required here - [key: string]: string | number -} - -const person: Person = { - name: "John", - age: 30, - email: "john@example.com", - phoneNumber: 1234567890, -} -``` - -**ArkTS** - -```typescript -class Person { - name: string - age: number - email: string - phoneNumber: number - - constructor(name: string, age: number, email: string, phoneNumber: number) { - this.name = name - this.age = age - this.email = email - this.phoneNumber = phoneNumber - } -} - -function main(): void { - const person: Person = new Person("John", 30, "john@example.com", 1234567890) -} -``` - -**See also** - -* Recipe: Objects with property names that are not identifiers are not supported -* Recipe: Symbol() API is not supported -* Recipe: Attempt to access an undefined property is a compile-time error -* Recipe: delete operator is not supported -* Recipe: typeof operator is allowed only in expression contexts -* Recipe: in operator is not supported -* Recipe: Property-based runtime type checks are not supported -* Recipe: Usage of standard library is restricted - ## Recipe: Enumeration members can be initialized only with compile time expressions of the same type **Rule `arkts-no-enum-mixed-types`** @@ -3347,7 +2925,7 @@ enum E2 { **Severity: error** -ArkTS does not support merging declratations for `enum`. Keep the +ArkTS does not support merging declarations for `enum`. Keep the declaration of each `enum` compact in the codebase. **TypeScript** @@ -3414,7 +2992,7 @@ MyNamespace.x = 2 **Severity: error** -ArkTS does not support statements in namespaces. Use a function to exectute +ArkTS does not support statements in namespaces. Use a function to execute statements. **TypeScript** @@ -3498,7 +3076,7 @@ import "path/to/module" **ArkTS** ```typescript -import * from "path/to/module" +import * as m from "path/to/module" ``` ## Recipe: `import default as ...` is not supported @@ -3591,6 +3169,9 @@ export class C2 { export { Class1 } from "module1" export { C2 as Class2 } from "module1" +// Re-exporting by wild-card is also supported: +// export * from "module1" + // consumer module import { Class1, Class2 } from "module2" ``` @@ -3746,7 +3327,7 @@ declare namespace N { } // Consuming code: -import * from "module" +import * as m from "module" console.log("N.foo called: ", N.foo(42)) ``` @@ -4115,7 +3696,7 @@ function readFileSync(path : string) : number[] { return [] } -function decodeImageSync(contrents : number[]) { +function decodeImageSync(contents : number[]) { // ... } @@ -4347,11 +3928,10 @@ Properties and functions of the global object: `eval`, * Recipe: Objects with property names that are not identifiers are not supported * Recipe: Symbol() API is not supported -* Recipe: Attempt to access an undefined property is a compile-time error +* Recipe: Indexed access is not supported for fields * Recipe: typeof operator is allowed only in expression contexts * Recipe: in operator is not supported * Recipe: Property-based runtime type checks are not supported -* Recipe: Dynamic property declaration is not supported * Recipe: globalThis is not supported ## Recipe: Strict type checking is enforced @@ -4563,3 +4143,4 @@ class C { n: number = 0 } ``` + diff --git a/zh-cn/application-dev/quick-start/typescript-to-arkts-migration-guide.md b/zh-cn/application-dev/quick-start/typescript-to-arkts-migration-guide.md index 9b3f5c465425e460dbc17728550509929aa1ba5e..4497a9775dca7274e4f1f08dd572e8bc85f0a9ed 100644 --- a/zh-cn/application-dev/quick-start/typescript-to-arkts-migration-guide.md +++ b/zh-cn/application-dev/quick-start/typescript-to-arkts-migration-guide.md @@ -3,10 +3,10 @@ 本文通过提供简洁的约束指导如何将标准的TypeScript代码重构为ArkTS代码。尽管ArkTS是基于TypeScript设计的,但出于性能考虑,一些TypeScript的特性被限制了。因此,在ArkTS中,所有的TypeScript特性被分成三类。 1. **完全支持的特性**:原始代码无需任何修改。根据测试,对于已遵循最佳TypeScript实践的项目,代码库中90%到97%的内容可以保持原封不动。 -2. **部分支持的特性**:需小规模的代码重构。例如,必须使用关键字`let`代替`var`来声明变量。注意,根据本文提供的约束进行代码重构后,您的代码仍为有效的TypeScript代码。 +2. **部分支持的特性**:需小规模的代码重构。例如,必须使用关键字`let`代替`var`来声明变量。 3. **不支持的特性**:需大规模的代码重构。例如,不支持`any`类型,所有使用`any`的代码都需要引入显式类型。 -本文将逐一介绍所有部分支持和所有不支持的特性,并提供代码重构的建议。对于没有提到的特性,则说明ArkTS完全支持。 +本文将逐一介绍所有部分支持和所有不支持的特性,并提供代码重构的建议。根据本文提供的约束进行代码重构后代码仍为有效的TypeScript代码。对于没有提到的特性,则说明ArkTS完全支持。 **示例** @@ -49,7 +49,7 @@ ArkTS在设计之初,就确定了如下目标: - ArkTS代码需非常容易阅读和理解,因为代码的阅读频率高于编写频率。 - 以最小功耗快速执行代码,这点对于移动设备(ArkTS的目标设备)来说至关重要。 -静态类型是ArkTS最重要的特性之一。使用静态类型有助于实现上述两个目标。如果程序采用静态类型,即所有类型在编译时都是已知的,那么开发者就能够容易理解代码中使用了哪些数据结构。同时,由于所有类型在程序实际运行前都是已知的,编译器可以提前验证代码的正确性,从而可以减少运行时类型检查项,有助于性能提升。 +静态类型是ArkTS最重要的特性之一。使用静态类型有助于实现上述两个目标。如果程序采用静态类型,即所有类型在编译时都是已知的,那么开发者就能够容易理解代码中使用了哪些数据结构。同时,由于所有类型在程序实际运行前都是已知的,编译器可以提前验证代码的正确性,从而可以减少运行时的类型检查,有助于性能提升。 基于上述考虑,ArkTS中禁止使用`any`类型。 @@ -107,24 +107,24 @@ class Point { // 无法从对象中删除某个属性,从而确保所有Point对象都具有属性x: let p1 = new Point(1.0, 1.0) -delete p1.x // 无论使用TypeScript还是ArkTS,都会产生编译时错误 -delete (p1 as any).x // 使用TypeScript时,不会报错;使用ArkTS时,会产生编译时错误 +delete p1.x // 在TypeScript和ArkTS中,都会产生编译时错误 +delete (p1 as any).x // 在TypeScript中不会报错;在ArkTS中会产生编译时错误 -// Point类没有定义命名为`z`的属性,在程序运行时也无法添加该属性: +// Point类没有定义命名为z的属性,在程序运行时也无法添加该属性: let p2 = new Point(2.0, 2.0) -p2.z = "Label"; // 无论使用TypeScript还是ArkTS,都会产生编译时错误 -(p2 as any).z = "Label" // 使用TypeScript时,不会报错;使用ArkTS时,会产生编译时错误 +p2.z = "Label"; // 在TypeScript和ArkTS中,都会产生编译时错误 +(p2 as any).z = "Label" // 在TypeScript中不会报错;在ArkTS中会产生编译时错误 -// 确保所有Point对象只有属性x和y,并且无法产生一些任意标识符并将其用作新属性: +// 类的定义确保了所有Point对象只有属性x和y,并且无法被添加其他属性: let p3 = new Point(3.0, 3.0) -let prop = Symbol(); // 使用TypeScript时,不会报错;使用ArkTS时,会产生编译时错误 -(p3 as any)[prop] = p3.x // 使用TypeScript时,不会报错;使用ArkTS时,会产生编译时错误 -p3[prop] = p3.x // 无论使用TypeScript还是ArkTS,都会产生编译时错误 +let prop = Symbol(); // 在TypeScript中不会报错;在ArkTS中会产生编译时错误 +(p3 as any)[prop] = p3.x // 在TypeScript中不会报错;在ArkTS中会产生编译时错误 +p3[prop] = p3.x // 在TypeScript和ArkTS中,都会产生编译时错误 -// 确保所有Point对象都具有number类型的属性x和y。因此,无法赋予其他类型的值给该属性: +// 类的定义确保了所有Point对象的属性x和y都具有number类型,因此,无法将其他类型的值赋值给它们: let p4 = new Point(4.0, 4.0) -p4.x = "Hello!"; // 无论使用TypeScript还是ArkTS,都会产生编译时错误 -(p4 as any).x = "Hello!" // 使用TypeScript时,不会报错;使用ArkTS时,会产生编译时错误 +p4.x = "Hello!"; // 在TypeScript和ArkTS中,都会产生编译时错误 +(p4 as any).x = "Hello!" // 在TypeScript中不会报错;在ArkTS中会产生编译时错误 // 使用符合类定义的Point对象: function distance(p1 : Point, p2 : Point) : number { @@ -148,22 +148,18 @@ console.log("Distance between p5 and p6: " + distance(p5, p6)) **示例** ```typescript -// 运算符`+`可以用于数字和字符串,但不能用于其他类型: -class C { - // ... -} -let c1 : C = new C() -let c2 : C = new C() -console.log(c1 + c2) // 编译时报错 +// 一元运算符`+`只能作用于数值类型: +console.log(+42) // 合法运算 +console.log(+"42") // 编译时错误 ``` 使用额外的语义重载语言运算符会增加语言规范的复杂度,而且,开发者还被迫牢记所有可能的例外情况及对应的处理规则。在某些情况下,产生一些不必要的运行时开销。 当前只有不到1%的代码库使用该特性。因此,尽管限制运算符的语义需要重构代码,但重构量很小且非常容易操作,并且,通过重构能使代码更清晰、具备更高性能。 -### (暂时)不支持 structural typing +### 不支持 structural typing -假设两个不相关的类`T`和`U`拥有相同的公共API: +假设两个不相关的类`T`和`U`拥有相同的`public`API: ```typescript class T { @@ -203,8 +199,8 @@ greeter(t) // 是否允许? 换句话说,我们将采取下面哪种方法呢: -- `T`和`U`没有继承关系或没有任何公共接口,但由于它们具有相同的公共API,它们“在某种程度上是相等的”,所以上述两个问题的答案都是“是”; -- `T`和`U`没有继承关系或没有任何公共接口,应当始终被视为完全不同的类型,因此上述两个问题的答案都是“否”。 +- `T`和`U`没有继承关系或没有`implements`相同的接口,但由于它们具有相同的`public`API,它们“在某种程度上是相等的”,所以上述两个问题的答案都是“是”; +- `T`和`U`没有继承关系或没有`implements`相同的接口,应当始终被视为完全不同的类型,因此上述两个问题的答案都是“否”。 采用第一种方法的语言支持structural typing,而采用第二种方法的语言则不支持structural typing。目前TypeScript支持structural typing,而ArkTS不支持。 @@ -254,12 +250,11 @@ console.log(z.get(2)) **相关约束** * 不支持Symbol() API -* 访问未定义的属性将导致编译时错误 +* 不支持通过索引访问字段 * 不支持delete运算符 * 仅允许在表达式中使用typeof运算符 * 不支持in运算符 * 禁止运行时检查对象属性 -* 不支持声明动态属性 * 限制使用标准库 @@ -271,6 +266,8 @@ console.log(z.get(2)) TypeScript中的`Symbol()`API用于在运行时生成唯一的属性名称。由于该API的常见使用场景在静态类型语言中没有意义,因此,ArkTS不支持`Symbol()`API。在ArkTS中,对象布局在编译时就确定了,且不能在运行时被更改。 +ArkTS也不支持`Symbol.iterator`和`Iterable interface`。请使用数组或容器。 + **TypeScript** ```typescript @@ -278,6 +275,26 @@ const sym = Symbol() let o = { [sym]: "value" } + +let obj = { + data: ['a', 'b', 'c'], + [Symbol.iterator]() { + const this_ = this + let index = 0 + return { + next() { + return { + done: index >= this_.data.length, + value: 'name_' + this_.data[index++] + } + } + } + } +} + +for (let t of obj) { + console.log(t) +} ``` **ArkTS** @@ -287,17 +304,21 @@ class SomeClass { public someProperty : string = "" } let o = new SomeClass() + +let arr:string[] = ['a', 'b', 'c'] +for (let t of arr) { + console.log('name_' + t) +} ``` **相关约束** * 仅支持属性名为标识符的对象 -* 访问未定义的属性将导致编译时错误 +* 不支持通过索引访问字段 * 不支持delete运算符 * 仅允许在表达式中使用typeof运算符 * 不支持in运算符 * 禁止运行时检查对象属性 -* 不支持声明动态属性 * 限制使用标准库 ### 不支持以`#`开头的私有字段 @@ -324,13 +345,13 @@ class C { } ``` -### 类型、命名空间等的命名必须唯一 +### 类型、命名空间的命名必须唯一 **规则:**`arkts-unique-names` **级别:错误** -类型、命名空间等的命名必须唯一,且能够与其他名称(例如:变量名)区分开来。 +类型(类、接口、枚举)、命名空间的命名必须唯一,且与其他名称(例如:变量名、函数名)不同。 **TypeScript** @@ -830,97 +851,100 @@ class Point {x: number = 0; y: number = 0} type N = number ``` -### 不支持索引访问字段 +### 不支持通过索引访问字段 **规则:**`arkts-no-props-by-index` **级别:错误** -ArkTS不支持通过索引访问对象的字段。改用点操作符。 +ArkTS不支持动态声明字段,不支持动态访问字段。只能访问已在类中声明或者继承可见的字段,访问其他字段将会造成编译时错误。 +使用点操作符访问字段,例如(`obj.field`),不支持索引访问(`obj[field]`)。 ArkTS支持通过索引访问`TypedArray`(例如`Int32Array`)中的元素。 **TypeScript** ```typescript -class Point {x: number = 0; y: number = 0} +class Point { + x: number = 0 + y: number = 0 +} let p: Point = {x: 1, y: 2} -let x = p["x"] +console.log(p["x"]) + +class Person { + name: string = "" + age: number = 0; + [key: string]: string | number +} + +let person: Person = { + name: "John", + age: 30, + email: "***@example.com", + phoneNumber: "18*********", +} ``` **ArkTS** ```typescript -class Point {x: number = 0; y: number = 0} +class Point { + x: number = 0 + y: number = 0 +} let p: Point = {x: 1, y: 2} -let x = p.x +console.log(p.x) + +class Person { + name: string + age: number + email: string + phoneNumber: string + + constructor(name: string, age: number, email: string, + phoneNumber: string) { + this.name = name + this.age = age + this.email = email + this.phoneNumber = phoneNumber + } +} + +let person = new Person("John", 30, "***@example.com", "18*********") +console.log(person["name"]) // 编译时错误 +console.log(person.unknownProperty) // 编译时错误 let arr = new Int32Array(1) console.log(arr[0]) ``` -### 不支持structural identity +### 不支持structural typing -**规则:**`arkts-no-structural-identity` +**规则:**`arkts-no-structural-typing` **级别:错误** -目前ArkTS不支持structural identity,即编译器无法比较两种类型的公共API并决定它们是否相同。可改用其他机制,例如继承、接口或类型别名。 - -对于下面的示例,类型`X`和`Y`在TypeScript中是等价的(可互换),而在ArkTS中,他们是不等价的。 +ArkTS不支持structural typing,编译器无法比较两种类型的`public`API并决定它们是否相同。使用其他机制,例如继承、接口或类型别名。 **TypeScript** ```typescript -interface X { - f(): string -} - -interface Y { // Y等于X +interface I1 { f(): string } -``` -**ArkTS** - -```typescript -interface X { +interface I2 { // I2等价于I1 f(): string } -type Y = X // Y等于X -``` - -**相关约束** - -* 子类型/父类型不支持structural typing -* 赋值检查不支持structural typing -* 类型推断不支持structural typing - -### 子类型/父类型不支持structural typing - -**规则:**`arkts-no-structural-subtyping` - -**级别:错误** - -当前ArkTS在类型推导时不会检查structural是否相同,即编译器无法比较两种类型的公共API并决定它们是否相同。改用其他机制,例如继承或接口。 - -**TypeScript** - -```typescript class X { - public foo: number - - constructor() { - this.foo = 0 - } + n: number = 0 + s: string = "" } -class Y { - public foo: number - - constructor() { - this.foo = 0 - } +class Y { // Y等价于X + n: number = 0 + s: string = "" } let x = new X() @@ -931,118 +955,80 @@ y = x console.log("Assign Y to X") x = y -``` - -**ArkTS** -```typescript -class X { - public foo: number - - constructor() { - this.foo = 0 - } +function foo(x: X) { + console.log(x.n, x.s) } -// Y从X派生,显式定义继承关系 -class Y extends X { - constructor() { - super() - } -} - -let x = new X() -let y = new Y() - -console.log("Assign Y to X") -x = y // ok, X是Y的父类 - -// 不能将X赋值给Y -// y = x -编译时错误 +// 由于X和Y的API是等价的,所以X和Y是等价的 +foo(new X()) +foo(new Y()) ``` -**相关约束** - -* 不支持structural identity -* 赋值检查不支持structural typing -* 类型推断不支持structural typing - -### 赋值检查不支持structural typing - -**规则:**`arkts-no-structural-assignability` - -**级别:错误** - -当前ArkTS在检查变量是否可相互赋值时不检查结构等价性,即编译器无法比较两种类型的公共API并决定它们是否相同。改用其他机制,例如继承或接口。 - -**TypeScript** +**ArkTS** ```typescript -class X { - public foo: number +interface I1 { + f(): string +} - constructor() { - this.foo = 0 - } +type I2 = I1 // I2是I1的别名 + +class B { + n: number = 0 + s: string = "" } -class Y { - public foo: number +// D是B的继承类,构建了子类型和父类型的关系 +class D extends B { constructor() { - this.foo = 0 + super() } } -let x = new X() -let y = new Y() - -console.log("Assign X to Y") -y = x +let b = new B() +let d = new D() -console.log("Assign Y to X") -x = y -``` +console.log("Assign D to B") +b = d // 合法赋值,因为B是D的父类 -**ArkTS** +// 将b赋值给d将会引起编译时错误 +// d = b -```typescript interface Z { - foo: number + n: number + s: string } -// X实现了接口Z,显式化定义了X和Y之间的关系。 +// 类X implements 接口Z,构建了X和Y的关系 class X implements Z { - public foo: number - - constructor() { - this.foo = 0 - } + n: number = 0 + s: string = "" } -// Y实现了接口Z,显式化定义了X和Y之间的关系。 +// 类Y implements 接口Z,构建了X和Y的关系 class Y implements Z { - public foo: number - - constructor() { - this.foo = 0 - } + n: number = 0 + s: string = "" } let x: Z = new X() let y: Z = new Y() console.log("Assign X to Y") -y = x // ok,两者类型相同 +y = x // 合法赋值,它们是相同的类型 console.log("Assign Y to X") -x = y // ok,两者类型相同 -``` +x = y // 合法赋值,它们是相同的类型 -**相关约束** +function foo(c: Z): void { + console.log(c.n, c.s) +} -* 不支持structural identity -* 子类型/父类型不支持structural typing -* 类型推断不支持structural typing +// 类X和类Y implement 相同的接口,因此下面的两个函数调用都是合法的 +foo(new X()) +foo(new Y()) +``` ### 显式标注泛型函数类型实参,除非可以从参数中推断出类型实参 @@ -1084,105 +1070,13 @@ function greet(): T { let z = greet() ``` -### 类型推断不支持structural typing - -**规则:**`arkts-no-structural-inference` - -**级别:错误** - -当前ArkTS不支持structural typing,即编译器无法比较两种类型的公共API并决定它们是否相同。使用继承和接口显式指定类型之间的关系。 - -**TypeScript** - -```typescript -class X { - public foo: number - private s: string - - constructor (f: number) { - this.foo = f - this.s = "" - } - - public say(): void { - console.log("X = ", this.foo) - } -} - -class Y { - public foo: number - - constructor (f: number) { - this.foo = f - } - public say(): void { - console.log("Y = ", this.foo) - } -} - -function bar(z: X): void { - z.say() -} - -// X和Y具有相同的公共API,因此它们是等价的。 -// 允许第二次调用 -bar(new X(1)) -bar(new Y(2) as X) -``` - -**ArkTS** - -```typescript -interface Z { - say(): void -} - -class X implements Z { - public foo: number - private s: string - - constructor (f: number) { - this.foo = f - this.s = "" - } - public say(): void { - console.log("X = ", this.foo) - } -} - -class Y implements Z { - public foo: number - - constructor (f: number) { - this.foo = f - } - public say(): void { - console.log("Y = ", this.foo) - } -} - -function bar(z: Z): void { - z.say() -} - -// X和Y实现了相同的接口Z,因此两个调用均允许: -bar(new X(1)) -bar(new Y(2)) -``` - -**相关约束** - -* 不支持structural identity -* 子类型/父类型不支持structural typing -* 赋值检查不支持structural typing - ### 不支持使用正则字面量 **规则:**`arkts-no-regexp-literals` **级别:错误** -当前ArkTS不支持正则字面量。改用通过`RegExp()`创建。 +当前ArkTS不支持正则字面量。请使用`RegExp()`创建正则对象。 **TypeScript** @@ -1253,7 +1147,7 @@ function id_x_y(o: Point): Point { return o } -// 因为TS支持structural typing,编译器可以推断p的类型为Point +// TS支持structural typing,可以推断p的类型为Point let p = {x: 5, y: 10} id_x_y(p) @@ -1518,54 +1412,6 @@ class C1 implements C { } ``` -### 访问未定义的属性将导致编译时错误 - -**规则:**`arkts-no-undefined-prop-access` - -**级别:错误** - -ArkTS仅支持访问那些在类中已声明或通过继承可访问的属性。禁止访问任何其他属性,否则会导致编译时错误。使用恰当的类型可以帮助编译期进行类型检查,确定属性是否存在。 - -**TypeScript** - -```typescript -let person = {name: "Bob", isEmployee: true} - -let n = person["name"] -let e = person["isEmployee"] -let s = person["office"] // 只有在开启noImplicitAny选项时会产生编译时错误 -``` - -**ArkTS** - -```typescript -class Person { - constructor(name: string, isEmployee: boolean) { - this.name = name - this.isEmployee = isEmployee - } - - name: string - isEmployee: boolean -} - -let person = new Person("Bob", true) -let n = person.name -let e = person.isEmployee -let s = person.office // 编译时错误 -``` - -**相关约束** - -* 对象的属性名必须是合法的标识符 -* 不支持Symbol() API -* 不支持delete运算符 -* 仅允许在表达式中使用typeof运算符 -* 不支持in运算符 -* 禁止运行时检查对象属性 -* 不支持声明动态属性 -* 限制使用标准库 - ### 类型转换仅支持`as T`语法 **规则:**`arkts-as-casts` @@ -1721,11 +1567,10 @@ p.y = null * 对象的属性名必须是合法的标识符 * 不支持Symbol() API -* 访问未定义的属性将导致编译时错误 +* 不支持通过索引访问字段 * 仅允许在表达式中使用typeof运算符 * 不支持in运算符 * 禁止运行时检查对象属性 -* 不支持声明动态属性 ### 仅允许在表达式中使用`typeof`运算符 @@ -1761,66 +1606,12 @@ let s2: string * 对象的属性名必须是合法的标识符 * 不支持Symbol() API -* 访问未定义的属性将导致编译时错误 +* 不支持通过索引访问字段 * 不支持delete运算符 * 不支持in运算符 * 禁止运行时检查对象属性 -* 不支持声明动态属性 * 限制使用标准库 -### 二元运算符`+`仅支持数字和字符串的隐式转换 - -**规则:**`arkts-no-polymorphic-plus` - -**级别:错误** - -如果二元运算符`+`的一个操作数是`string`类型(包括enum中的`string`),那么另一个操作数可以是任意的类型,在运算时它的值被隐式转换成`string`。在其他情况下,ArkTS只支持`number`和enum中的`number`的隐式转换。 -正如TypeScript一样,ArkTS不支持两个`boolean`类型的值相加。其他情形下,都需要显式转换为字符串。 - -**TypeScript** - -```typescript -enum E { E1, E2 } - -let a = 10 + 32 // 42 -let b = E.E1 + 10 // 10 -let c = 10 + "5" // "105" - -let d = "5" + E.E2 // "51" -let e = "Hello, " + "world!" // "Hello, world!" -let f = "string" + true // "stringtrue" - -let g = (new Object()) + "string" // "[object Object]string" - -let i = true + true // 编译时错误 -let j = true + 2 // 编译时错误 -let k = E.E1 + true // 编译时错误 -``` - -**ArkTS** - -```typescript -enum E { E1, E2 } - -let a = 10 + 32 // 42 -let b = E.E1 + 10 // 10 -let c = 10 + "5" // "105" - -let d = "5" + E.E2 // "51" -let e = "Hello, " + "world!" // "Hello, world!" -let f = "string" + true // "stringtrue" - -let g = (new Object()).toString() + "string" - -let i = true + true // 编译时错误 -let j = true + 2 // 编译时错误 -let k = E.E1 + true // 编译时错误 -``` - -**相关约束** - -* 一元运算符+、-和~仅适用于数值类型 - ### 部分支持`instanceof`运算符 **规则:**`arkts-instanceof-ref-types` @@ -1889,11 +1680,10 @@ let b = p instanceof Person // true,且属性name一定存在 * 对象的属性名必须是合法的标识符 * 不支持Symbol() API -* 访问未定义的属性将导致编译时错误 +* 不支持通过索引访问字段 * 不支持delete运算符 * 仅允许在表达式中使用typeof运算符 * 禁止运行时检查对象属性 -* 不支持声明动态属性 * 限制使用标准库 ### 不支持解构赋值 @@ -2008,33 +1798,6 @@ let x = zp.x let y = zp.y ``` -### 不支持隐含类型的推断 - -**规则:**`arkts-no-implied-inference` - -**级别:错误** - -目前ArkTS不支持隐含类型的推断,改用显式的类型标注。如果容器中有不同类型的数据,请使用`Object[]`。 - -**TypeScript** - -```typescript -let [a, b, c] = [1, "hello", true] -``` - -**ArkTS** - -```typescript -let a = 1 -let b = "hello" -let c = true - -let arr: Object[] = [1, "hello", true] -let a1 = arr[0] -let b1 = arr[1] -let c1 = arr[2] -``` - ### 不支持在catch语句标注类型 **规则:**`arkts-no-types-in-catch` @@ -2097,23 +1860,8 @@ for (let i = 0; i < a.length; ++i) { **相关约束** -* 不支持可迭代接口 * for-of仅适用于数组和字符串 -### 不支持可迭代接口 - -**规则:**`arkts-no-iterable` - -**级别:错误** - -ArkTS不支持`Symbol`API、`Symbol.iterator`和最终可迭代的接口。请使用数组和标准库中的容器。 - -**相关约束** - -* 不支持Symbol() API -* 不支持for .. in -* for-of仅支持数组和字符串 - ### `for-of`仅适用于数组和字符串 **规则:**`arkts-for-of-str-arr` @@ -2144,7 +1892,6 @@ for (let n of numbers) { **相关约束** * 不支持for .. in -* 不支持可迭代接口 ### 不支持映射类型 @@ -2204,92 +1951,6 @@ let r: number = 42 console.log("Area: ", Math.PI * r * r) ``` -### `case`语句仅支持编译期值 - -**规则:**`arkts-no-computed-case` - -**级别:错误** - -在ArkTS中,`case`语句仅支持编译期值,支持`const`常量和`class`的`static readonly`属性。若值无法在编译期确定,请使用`if`语句。 - -**TypeScript** - -```typescript -let x = 2 -let y = 3 -switch (x) { - case 1: - console.log(1) - break - case 2: - console.log(2) - break - case y: - console.log(y) - break - default: - console.log("other") -} -``` - -**ArkTS** - -```typescript -let x = 2 -switch (x) { - case 1: - console.log(1) - break - case 2: - console.log(2) - break - case 3: - console.log(3) - break - default: - console.log("other") -} -``` - -### 限制`switch`语句中表达式的类型 - -**规则:**`arkts-limited-switch` - -**级别:错误** - -ArkTS支持`switch`语句中使用`number`, `Number`, `string`, `String`或者`enum`类型的值。其他情况下请使用`if`语句。 - -**TypeScript** - -```typescript -class Point { - x: number = 0 - y: number = 0 -} - -let a = new Point() - -switch (a) { - case null: break - default: console.log("not null") -} -``` - -**ArkTS** - -```typescript -class Point { - x: number = 0 - y: number = 0 -} - -let a = new Point() - -if (a != null) { - console.log("not null") -} -``` - ### 限制`throw`语句中表达式的类型 **规则:**`arkts-limited-throw` @@ -2453,7 +2114,7 @@ function addNum(a: number, b: number): void { **级别:错误** -ArkTS不支持在函数中使用`this`。只能在方法中使用`this`。 +ArkTS不支持在函数和静态方法中使用`this`。只能在方法中使用`this`。 **TypeScript** @@ -2823,7 +2484,7 @@ class C implements Mover, Shaker { **级别:错误** -ArkTS不支持合并声明。所用类、接口等的声明必须唯一。 +ArkTS不支持类、接口的声明合并。 **TypeScript** @@ -2940,11 +2601,10 @@ function main(): void { * 对象的属性名必须是合法的标识符 * 不支持Symbol() API -* 访问未定义的属性将导致编译时错误 +* 不支持通过索引访问字段 * 不支持delete运算符 * 仅允许运算符typeof在表达式上下文中使用 * 不支持in运算符 -* 不支持声明动态属性 * 限制使用标准库 ### 不支持构造函数类型 @@ -2996,65 +2656,7 @@ let Impersonizer: PersonCtor = (n: string, a: number): Person => { const person = createPerson(Impersonizer, "John", 30) ``` -### 不支持声明动态属性 - -**规则:**`arkts-no-dyn-prop-decl` - -**级别:错误** - -ArkTS不支持声明动态属性。必须在类中声明所有的属性。尽管可以用对象数组来实现动态特性,但更推荐使用静态类型范式来显式声明字段、名称和类型。 - -**TypeScript** - -```typescript -class Person { - name: string = "" - age: number = 0; // 此处需要分号 - [key: string]: string | number -} - -const person: Person = { - name: "John", - age: 30, - email: "***@example.com", - phoneNumber: 18*********, -} -``` - -**ArkTS** - -```typescript -class Person { - name: string - age: number - email: string - phoneNumber: number - - constructor(name: string, age: number, email: string, phoneNumber: number) { - this.name = name - this.age = age - this.email = email - this.phoneNumber = phoneNumber - } -} - -function main(): void { - const person: Person = new Person("John", 30, "***@example.com", 18*********) -} -``` - -**相关约束** - -* 对象的属性名必须是合法的标识符 -* 不支持Symbol() API -* 访问未定义的属性将导致编译时错误 -* 不支持delete运算符 -* 仅允许在表达式中使用typeof运算符 -* 不支持in运算符 -* 禁止运行时检查对象属性 -* 限制使用标准库 - -### 只能使用类型相同的编译期表达式初始化枚举成员 +### 只能使用类型相同的编译时表达式初始化枚举成员 **规则:**`arkts-no-enum-mixed-types` @@ -3304,7 +2906,7 @@ import * as m from "mod" **级别:错误** -ArkTS支持大多数场景下的重导出,例如命名重导出和重命名重导出。不支持`export * as ...`。 +ArkTS支持命名重导出和重命名重导出。支持`export * ...`的语法,不支持`export * as ...`的语法。 **TypeScript** @@ -3341,6 +2943,9 @@ export class Class2 { export { Class1 } from "module1" export { C2 as Class2 } from "module1" +// 支持以下语法 +// export * from "module1" + // consumer模块 import { Class1, Class2 } from "module2" @@ -4061,16 +3666,15 @@ ArkTS不允许使用TypeScript或JavaScript标准库中的某些接口。大部 * 对象的属性名必须是合法的标识符 * 不支持Symbol() API -* 访问未定义的属性将导致编译时错误 +* 不支持通过索引访问字段 * 仅允许在表达式中使用typeof运算符 * 不支持in运算符 * 禁止运行时检查对象属性 -* 不支持声明动态属性 * 不支持globalThis ### 强制开启严格类型检查 -**规则 `arkts-strict-typing`** +**规则:**`arkts-strict-typing` **级别:错误** @@ -4122,7 +3726,7 @@ let n2: number = 0 ### 不允许通过注释关闭类型检查 -**规则 `arkts-strict-typing-required`** +**规则:**`arkts-strict-typing-required` **级别:错误** @@ -4156,7 +3760,7 @@ let s2: string = null // 编译时报错 ### 允许ArkTS代码导入TS代码, 不允许TS代码导入ArkTS代码 -**规则 `arkts-no-ts-deps`** +**规则:**`arkts-no-ts-deps` **级别:错误** @@ -4188,7 +3792,7 @@ import { C } from "lib1" ### 除了ArkUI中的装饰器,不允许使用其他装饰器 -**规则 `arkts-no-decorators-except-arkui`** +**规则:**`arkts-no-decorators-except-arkui` **级别:错误**