未验证 提交 3bb87d10 编写于 作者: O openharmony_ci 提交者: Gitee

!21946 更新ArkTS文档

Merge pull request !21946 from huoqingyi/arkts_docs_v1
...@@ -48,12 +48,17 @@ applications in ArkTS. ...@@ -48,12 +48,17 @@ applications in ArkTS.
## Declarations ## Declarations
Declarations in ArkTS introduce variables, constants, functions and types. Declarations in ArkTS introduce:
- variables,
- constants,
- functions, and
- types.
### Variable Declaration ### Variable Declaration
Declaration started with keyword `let` introduces a variable which can have different values A declaration starting with the keyword `let` introduces a variable which
during program execution. can have different values during program execution.
```typescript ```typescript
let hi: string = "hello" let hi: string = "hello"
...@@ -62,18 +67,19 @@ hi = "hello, world" ...@@ -62,18 +67,19 @@ hi = "hello, world"
### Constant Declaration ### Constant Declaration
Declaration started with keyword `const` introduces a read-only constant that can be assigned only once. A declaration starting with the keyword `const` introduces a read-only
constant that can be assigned only once.
```typescript ```typescript
const hello: string = "hello" const hello: string = "hello"
``` ```
Assigning a new value to a constant is a compile-time error. A compile-time error occurs if a new value is assigned to a constant.
### Automatic Type Inference ### Automatic Type Inference
As ArkTS is a statically typed language, the types of all entities, like As ArkTS is a statically typed language, the types of all entities, like
variables and constants have to be known at compile time. variables and constants, have to be known at compile time.
However, developers do not need to explicitly specify the type of a declared However, developers do not need to explicitly specify the type of a declared
entity if a variable or a constant declaration contains an initial value. entity if a variable or a constant declaration contains an initial value.
...@@ -90,8 +96,8 @@ let hi2 = "hello, world" ...@@ -90,8 +96,8 @@ let hi2 = "hello, world"
## Types ## Types
`Class`, `interface`, `function`, `enum`, `union` types and type `aliases` are `Class`, `interface`, `function`, `enum`, `union` types, and type
described in the corresponding sections. `aliases` are described in the corresponding sections.
### Numeric Types ### Numeric Types
...@@ -104,9 +110,9 @@ with the decimal base. ...@@ -104,9 +110,9 @@ with the decimal base.
Integer literals include the following: Integer literals include the following:
* decimal integers that consist of a sequence of digits. For example: `0`, `117`, `-345`; * decimal integers that consist of a sequence of digits. For example: `0`, `117`, `-345`;
* hexadecimal integers that start with 0x (or 0X) and can contain digits (0-9) and letters a-f or A-F. For example: `0x1123`, `0x00111`, `-0xF1A7`; * hexadecimal integers that start with 0x (or 0X), and can contain digits (0-9) and letters a-f or A-F. For example: `0x1123`, `0x00111`, `-0xF1A7`;
* octal integers that start with 0o (or 0O) and can only contain digits (0-7). For example: `0o777`; * octal integers that start with 0o (or 0O) and can only contain digits (0-7). For example: `0o777`;
* binary integers that start with 0b (or 0B) and can only contain the digits 0 and 1. For example: `0b11`, `0b0011`, `-0b11`. * binary integers that start with 0b (or 0B), and can only contain the digits 0 and 1. For example: `0b11`, `0b0011`, `-0b11`.
A floating-point literal includes the following: A floating-point literal includes the following:
...@@ -150,13 +156,12 @@ if (isDone) { ...@@ -150,13 +156,12 @@ if (isDone) {
### `String` ### `String`
A `string` is a sequence of characters; some characters can be set using A `string` is a sequence of characters; some characters can be set by using
escape-sequences. escape sequences.
A `string` literal consists of zero or more characters A `string` literal consists of zero or more characters enclosed in single
enclosed between single (’) or (’) or double quotes (“). The special form of string literals are template
double quotes (“). The special form of a string literals are template literals literals enclosed in backtick quotes (\`).
enclosed in backtick quotes (\`).
```typescript ```typescript
let s1 = "Hello, world!\n" let s1 = "Hello, world!\n"
...@@ -168,9 +173,8 @@ let s3 = `The result is ${a}` ...@@ -168,9 +173,8 @@ let s3 = `The result is ${a}`
### `Void` Type ### `Void` Type
The `void` type is used to specify that a function does not return a value. The `void` type is used to specify that a function does not return a value.
This type has the only one value, This type has the only one value which is also `void`. As `void` is
which is also `void`. As `void` is reference type, it can be used as type a reference type, it can be used as type argument for generic types.
argument for generic types.
```typescript ```typescript
class Class<T> { class Class<T> {
...@@ -181,19 +185,18 @@ let instance: Class <void> ...@@ -181,19 +185,18 @@ let instance: Class <void>
### `Object` Type ### `Object` Type
An `Object` class type is a base type for all reference types. Any value, including An `Object` class type is a base type for all reference types. Any value,
values of primitive types (they will be automatically boxed), can be directly assigned including values of primitive types (they will be automatically boxed), can
to variables of type `Object`. be directly assigned to variables of the type `Object`.
### `Array` Type ### `Array` Type
An `array` is an object comprised of elements of data types assignable to An `array` is an object comprised of elements of data types assignable to
the element type specified in the array declaration. the element type specified in the array declaration.
A value of an `array` is set using *array composite literal*, that is a list A value of an `array` is set by using *array composite literal*, that is a
of zero or more expressions list of zero or more expressions enclosed in square brackets ([]). Each
enclosed in square brackets ([]). Each expression represents an element of the expression represents an element of the `array`. The length of the `array`
`array`. The length of the `array` is set by the number of expressions. Index of is set by the number of expressions. Index of the first array element is 0.
the first array element is 0.
The following example creates the `array` with three elements: The following example creates the `array` with three elements:
...@@ -205,15 +208,16 @@ let names: string[] = ["Alice", "Bob", "Carol"] ...@@ -205,15 +208,16 @@ let names: string[] = ["Alice", "Bob", "Carol"]
An `enum` type is a value type with a defined set of named values called An `enum` type is a value type with a defined set of named values called
enum constants. enum constants.
To be used, an `enum` constant must be prefixed with an enum `type` name. In order to be used, an `enum` constant must be prefixed with an enum
`type` name.
```typescript ```typescript
enum Color { Red, Green, Blue } enum Color { Red, Green, Blue }
let c: Color = Color.Red let c: Color = Color.Red
``` ```
A constant expression can be A constant expression can be used to explicitly set the value of an `enum`
used to explicitly set the value of an enum constant. constant.
```typescript ```typescript
enum Color { White = 0xFF, Grey = 0x7F, Black = 0x00 } enum Color { White = 0xFF, Grey = 0x7F, Black = 0x00 }
...@@ -222,8 +226,9 @@ let c: Color = Color.Black ...@@ -222,8 +226,9 @@ let c: Color = Color.Black
### `Union` Type ### `Union` Type
An `union` type is a reference type which is created as a combination of other types. Values of the union types A `union` type is a reference type which is created as a combination
can be valid values of all types union was created from. of other types. Values of union types can be valid values of all types
a union was created from.
```typescript ```typescript
class Cat { class Cat {
...@@ -244,7 +249,8 @@ animal = 42 ...@@ -244,7 +249,8 @@ animal = 42
// One may assign the variable of the union type with any valid value // One may assign the variable of the union type with any valid value
``` ```
There are different mechanisms how to get a value of the particular type from the union. There are different mechanisms to get a value of a particular type from a union.
For example For example
```typescript ```typescript
...@@ -267,8 +273,8 @@ animal.sleep () // Any animal can sleep ...@@ -267,8 +273,8 @@ animal.sleep () // Any animal can sleep
### Type `Aliases` ### Type `Aliases`
Type `aliases` provide names for anonymous types (array, function, object literal or union Type `aliases` provide names for anonymous types (array, function, object
types) or alternative names for existing types. literal or union types) or alternative names for existing types.
```typescript ```typescript
type Matrix = number[][] type Matrix = number[][]
...@@ -284,7 +290,7 @@ type NullableObject = Object | null ...@@ -284,7 +290,7 @@ type NullableObject = Object | null
Simple assignment operator ‘=’ is used as in “x = y”. Simple assignment operator ‘=’ is used as in “x = y”.
Compound assignment operators combine an assignment with an operator, where Compound assignment operators combine an assignment with an operator, where
`x op = y` equals to `x = x op y`. `x op = y` equals `x = x op y`.
Compound assignment operators are as follows: `+=`, `-=`, `*=`, `/=`, Compound assignment operators are as follows: `+=`, `-=`, `*=`, `/=`,
`%=`, `<<=`, `>>=`, `>>>=`, `&=`, `|=`, `^=`. `%=`, `<<=`, `>>=`, `>>>=`, `&=`, `|=`, `^=`.
...@@ -299,10 +305,9 @@ Compound assignment operators are as follows: `+=`, `-=`, `*=`, `/=`, ...@@ -299,10 +305,9 @@ Compound assignment operators are as follows: `+=`, `-=`, `*=`, `/=`,
| `>=` | returns true if the left operand is greater than or equal to the right | | `>=` | returns true if the left operand is greater than or equal to the right |
| `<` | returns true if the left operand is less then the right | | `<` | returns true if the left operand is less then the right |
| `<=` | returns true if the left operand is less than or equal to the right | | `<=` | returns true if the left operand is less than or equal to the right |
### Arithmetic Operators ### Arithmetic Operators
Unary operators are `-`, `+`, `--`, `++`. Unary operators are `-`, `+`, `--` and `++`.
Binary operators are as follows: Binary operators are as follows:
...@@ -313,7 +318,6 @@ Binary operators are as follows: ...@@ -313,7 +318,6 @@ Binary operators are as follows:
| `*` | multiplication | | `*` | multiplication |
| `/` | division | | `/` | division |
| `%` | remainder after division | | `%` | remainder after division |
### Bitwise Operators ### Bitwise Operators
| Operator | Description | | Operator | Description |
...@@ -325,7 +329,6 @@ Binary operators are as follows: ...@@ -325,7 +329,6 @@ Binary operators are as follows:
| `a << b` | Shift left: shifts the binary representation of *a* to the left by *b* bits. | | `a << b` | Shift left: shifts the binary representation of *a* to the left by *b* bits. |
| `a >> b` | Arithmetic right shift: shifts the binary representation of *a* to the right by *b* bits with sign-extension. | | `a >> b` | Arithmetic right shift: shifts the binary representation of *a* to the right by *b* bits with sign-extension. |
| `a >>> b` | Logical right shift: shifts the binary representation of *a* to the right by *b* bits with zero-extension. | | `a >>> b` | Logical right shift: shifts the binary representation of *a* to the right by *b* bits with zero-extension. |
### Logical Operators ### Logical Operators
| Operator | Description | | Operator | Description |
...@@ -333,16 +336,15 @@ Binary operators are as follows: ...@@ -333,16 +336,15 @@ Binary operators are as follows:
| `a && b` | logical AND | | `a && b` | logical AND |
| `a \|\| b` | logical OR | | `a \|\| b` | logical OR |
| `! a` | logical NOT | | `! a` | logical NOT |
## Control Flow ## Control Flow
### `If` Statements ### `If` Statements
Use `if` statement to execute a sequence of statements when a logical An `if` statement is used to execute a sequence of statements when a logical
condition is true, or another set of statements (if provided) otherwise. condition is `true`, or another set of statements (if provided) otherwise.
`else` part may contain more `if` statements as well. The `else` part can also contain more `if` statements.
The `if` statement looks as follows: An `if` statement looks as follows:
```typescript ```typescript
if (condition1) { if (condition1) {
...@@ -354,7 +356,7 @@ if (condition1) { ...@@ -354,7 +356,7 @@ if (condition1) {
} }
``` ```
All conditional expressions should be of the type `boolean` or other types All conditional expressions must be of the type `boolean` or other types
(`string`, `number`, etc.). For types other than `boolean`, implicit (`string`, `number`, etc.). For types other than `boolean`, implicit
conversion rules apply: conversion rules apply:
...@@ -372,10 +374,10 @@ if (s2.length != 0) { ...@@ -372,10 +374,10 @@ if (s2.length != 0) {
### `Switch` Statements ### `Switch` Statements
Use `switch` statement to execute a sequence of statements that match the A `switch` statement is used to execute a sequence of statements that match
value of the switch expression. the value of a switch expression.
The `switch` statement looks as follows: A `switch` statement looks as follows:
```typescript ```typescript
switch (expression) { switch (expression) {
...@@ -396,7 +398,7 @@ default: ...@@ -396,7 +398,7 @@ default:
``` ```
The `switch` expression type must be of `number`, `enum` or `string` The `switch` expression type must be of `number`, `enum` or `string`
type. types.
Each label must be either a constant expression or the name of an enum constant. Each label must be either a constant expression or the name of an enum constant.
...@@ -409,14 +411,15 @@ default statements are executed. ...@@ -409,14 +411,15 @@ default statements are executed.
An optional `break` statement allows to break out of the `switch` and An optional `break` statement allows to break out of the `switch` and
continue executing the statement that follows the `switch`. continue executing the statement that follows the `switch`.
If there is no break, then the next statements in the `switch` is executed. If there is no `break`, then the next statements in the `switch` is
executed.
### Conditional Expressions ### Conditional Expressions
The conditional expression `?` : uses the `boolean` value of the first The conditional expression `? :` uses the `boolean` value of the first
expression to decide which of two other expressions to evaluate. expression to decide which of two other expressions to evaluate.
It looks as follows: A conditional expression looks as follows:
```typescript ```typescript
condition ? expression1 : expression2 condition ? expression1 : expression2
...@@ -435,8 +438,10 @@ let message = isValid ? 'Valid' : 'Failed' ...@@ -435,8 +438,10 @@ let message = isValid ? 'Valid' : 'Failed'
### `For` Statements ### `For` Statements
A `for` statement is executed repeatedly until the specified loop exit condition A `for` statement is executed repeatedly until the specified loop exit
is `false`. A `for` statement looks as follows: condition is `false`.
A `for` statement looks as follows:
```typescript ```typescript
for ([init]; [condition]; [update]) { for ([init]; [condition]; [update]) {
...@@ -446,10 +451,15 @@ for ([init]; [condition]; [update]) { ...@@ -446,10 +451,15 @@ for ([init]; [condition]; [update]) {
When a `for` statement is executed, the following process takes place: When a `for` statement is executed, the following process takes place:
1. An `init` expression is executed, if any. This expression usually initializes one or more loop counters. 1. An `init` expression is executed, if any. This expression usually
2. The condition is evaluated. If the value of condition is `true`, or if the conditional expression is omitted, then the statements in the for body are to be executed. If the value of condition is `false`, the `for` loop terminates. initializes one or more loop counters.
2. The condition is evaluated. If the value of condition is `true`, or
if the conditional expression is omitted, then the statements in the
`for` body are to be executed. If the value of condition is `false`,
then the `for` loop terminates.
3. The statements of the `for` body are executed. 3. The statements of the `for` body are executed.
4. If there is an `update` expression, the `update` expression is executed. 4. If there is an `update` expression, then the `update` expression
is executed.
5. Go back to step 2. 5. Go back to step 2.
Example: Example:
...@@ -463,8 +473,9 @@ for (let i = 0; i < 10; i += 2) { ...@@ -463,8 +473,9 @@ for (let i = 0; i < 10; i += 2) {
### `For-of` Statements ### `For-of` Statements
Use `for-of` statements to iterate over an array or string. A `for-of` `for-of` statements are used to iterate over an array or string.
statement looks as follows:
A `for-of` statement looks as follows:
```typescript ```typescript
for (forVar of expression) { for (forVar of expression) {
...@@ -480,8 +491,10 @@ for (let ch of "a string object") { /* process ch */ } ...@@ -480,8 +491,10 @@ for (let ch of "a string object") { /* process ch */ }
### `While` Statements ### `While` Statements
A `while` statement has its body statements executed as long as the specified condition A `while` statement has its body statements executed as long as the
evaluates to `true`. It looks as follows: specified condition evaluates to `true`.
A `while` statement looks as follows:
```typescript ```typescript
while (condition) { while (condition) {
...@@ -504,8 +517,10 @@ while (n < 3) { ...@@ -504,8 +517,10 @@ while (n < 3) {
### `Do-while` Statements ### `Do-while` Statements
The `do-while` statements are executed repetitively until the specified `do-while` statements are executed repetitively until a specified
condition evaluates to false. It looks as follows: condition evaluates to false.
A `do-while` statement looks as follows:
```typescript ```typescript
do { do {
...@@ -526,7 +541,7 @@ do { ...@@ -526,7 +541,7 @@ do {
### `Break` Statements ### `Break` Statements
Use a `break` statement to terminate any `loop` statement or `switch`. A `break` statement is used to terminate any `loop` statement or `switch`.
Example: Example:
...@@ -558,8 +573,8 @@ label: while (true) { ...@@ -558,8 +573,8 @@ label: while (true) {
### `Continue` Statements ### `Continue` Statements
A `continue` statement stops the execution of the current loop iteration and A `continue` statement stops the execution of the current loop iteration
passes control to the next iteration. and passes control to the next iteration.
Example: Example:
...@@ -575,13 +590,13 @@ for (let x = 0; x < 100; x++) { ...@@ -575,13 +590,13 @@ for (let x = 0; x < 100; x++) {
### `Throw` and `Try` Statements ### `Throw` and `Try` Statements
A `throw` statement is used to throw an exception or error: A `throw` statement is used to throw an exception or an error:
```typescript ```typescript
throw new Error("this error") throw new Error("this error")
``` ```
A `try` statement is used to catch and handle an exception or error: A `try` statement is used to catch and handle an exception or an error:
```typescript ```typescript
try { try {
...@@ -672,7 +687,7 @@ function hello(name?: string) { ...@@ -672,7 +687,7 @@ function hello(name?: string) {
Another form contains an expression that specifies a default value. Another form contains an expression that specifies a default value.
If the corresponding argument to such parameter is omitted in a function call, If the corresponding argument to such parameter is omitted in a function call,
then this parameter has the default value. then this parameter’s value is default.
```typescript ```typescript
function multiply(n: number, coeff: number = 2): number { function multiply(n: number, coeff: number = 2): number {
...@@ -701,7 +716,8 @@ sum(1, 2, 3) // returns 6 ...@@ -701,7 +716,8 @@ sum(1, 2, 3) // returns 6
## Return Types ## Return Types
If function return type can be inferred from its body content then it can be omitted from the function declaration. If function return type can be inferred from its body content, then it can
be omitted from the function declaration.
```typescript ```typescript
// Explicit return type // Explicit return type
...@@ -711,7 +727,9 @@ function foo(): string { return "foo" } ...@@ -711,7 +727,9 @@ function foo(): string { return "foo" }
function goo() { return "goo" } function goo() { return "goo" }
``` ```
The return type of a function that does not need to return a value may be explicitly specified as `void` or omitted altogether. No return statement is needed for such functions. The return type of a function that does not need to return a value can be
explicitly specified as `void` or omitted altogether. No return statement
is needed for such functions.
Both notations below are valid: Both notations below are valid:
...@@ -722,13 +740,16 @@ function hi2(): void { console.log("hi") } ...@@ -722,13 +740,16 @@ function hi2(): void { console.log("hi") }
## Function Scope ## Function Scope
Variables and other entities defined in a function are local to the function and cannot be accessed outside. Variables and other entities defined in a function are local to the function
and cannot be accessed from the outside.
If the name of a variable defined in the function is equal to the name of an entity in the outer scope, then the local definition shadows outer entity. If the name of a variable defined in the function is equal to the name of an
entity in the outer scope, then the local definition shadows the outer entity.
## Function Calls ## Function Calls
Calling a function actually leads to its body execution while arguments of the call are assigned to function parameters. Calling a function actually leads to the execution of its body, while
the arguments of the call are assigned to the function parameters.
If the function is defined as follows: If the function is defined as follows:
...@@ -770,9 +791,11 @@ let sum = (x: number, y: number): number => { ...@@ -770,9 +791,11 @@ let sum = (x: number, y: number): number => {
} }
``` ```
An arrow function return type may be omitted; in this case it is inferred from the function body. An arrow function return type can be omitted; in such case, it is inferred
from the function body.
An expression can be specified as an arrow function, making notation shorter, so the following two notations are equivalent: An expression can be specified as an arrow function to make the notation
shorter, i.e., the following two notations are equivalent:
```typescript ```typescript
let sum1 = (x: number, y: number) => { return x + y } let sum1 = (x: number, y: number) => { return x + y }
...@@ -781,10 +804,12 @@ let sum2 = (x: number, y: number) => x + y ...@@ -781,10 +804,12 @@ let sum2 = (x: number, y: number) => x + y
## Closure ## Closure
An arrow function is usually defined inside another function. As an inner function, it can access all variables and functions defined in the outer functions. An arrow function is usually defined inside another function. As an inner
function, it can access all variables and functions defined in the outer
functions.
To capture the context, an inner function forms a closure of its environment. To capture the context, an inner function forms a closure of its environment.
The closure allows accessing such inner function outside its own environment. The closure allows accessing such an inner function outside its own environment.
```typescript ```typescript
function f(): () => number { function f(): () => number {
...@@ -801,7 +826,10 @@ In the sample above, the arrow function closure captures the `count` variable. ...@@ -801,7 +826,10 @@ In the sample above, the arrow function closure captures the `count` variable.
## Function Overload Signatures ## Function Overload Signatures
A function can be specified to be called in different ways by writing overload signatures. To do so, several functions headers are written that they have the same name but different signatures, immediately followed by the single implementing function. A function can be specified to be called in different ways by writing
overload signatures. To do so, several functions’ headers that have the
same name but different signatures are written and immediately followed
by the single implementation function.
```typescript ```typescript
function foo(): void; /* 1st signature */ function foo(): void; /* 1st signature */
...@@ -814,13 +842,15 @@ foo() // ok, 1st signature is used ...@@ -814,13 +842,15 @@ foo() // ok, 1st signature is used
foo("aa") // ok, 2nd signature is used foo("aa") // ok, 2nd signature is used
``` ```
It is an error if two overload signatures have identical parameter lists. An error occurs if two overload signatures have identical parameter lists.
# Classes # Classes
A class declaration introduces a new type and defines its fields, methods and constructors. A class declaration introduces a new type and defines its fields, methods
and constructors.
In the following example, class `Person` is defined, which has fields ‘name’ and ‘surname’, constructor and a method `fullName`: In the following example, class `Person` is defined, which has fields
‘name’ and ‘surname’, constructor, and a method `fullName`:
```typescript ```typescript
class Person { class Person {
...@@ -836,21 +866,22 @@ class Person { ...@@ -836,21 +866,22 @@ class Person {
} }
``` ```
After the class is defined, its instances can be created using the keyword `new`: After the class is defined, its instances can be created by using
the keyword `new`:
```typescript ```typescript
let p = new Person("John", "Smith") let p = new Person("John", "Smith")
console.log(p.fullName()) console.log(p.fullName())
``` ```
Or an instance can be created using object literals: or an instance can be created by using object literals:
```typescript ```typescript
class Point { class Point {
x: number = 0 x: number = 0
y: number = 0 y: number = 0
} }
let p: Point = {42 ,42} let p: Point = {x: 42, y: 42}
``` ```
## Fields ## Fields
...@@ -877,7 +908,7 @@ let p1 = new Person("Alice", 25) ...@@ -877,7 +908,7 @@ let p1 = new Person("Alice", 25)
let p2 = new Person("Bob", 28) let p2 = new Person("Bob", 28)
``` ```
To access an instance field, use an instance of the class: An instance of the class is used to access an instance field:
```typescript ```typescript
p1.name p1.name
...@@ -886,10 +917,11 @@ this.name ...@@ -886,10 +917,11 @@ this.name
### Static Fields ### Static Fields
Use the keyword `static` to declare a field as static. Static fields belong The keyword `static` is used to declare a field as static. Static fields
to the class itself, and all instances of the class share one static field. belong to the class itself, and all instances of the class share one static
field.
To access a static field, use the class name: The class name is used to access a static field:
```typescript ```typescript
class Person { class Person {
...@@ -906,9 +938,11 @@ console.log(Person.numberOfPersons) ...@@ -906,9 +938,11 @@ console.log(Person.numberOfPersons)
### Getters and Setters ### Getters and Setters
Setters and getters can be used to provide controlled access to object properties. Setters and getters can be used to provide controlled access to object
properties.
In the following example, a setter is used to forbid setting invalid values of the ‘age’ property: In the following example, a setter is used to forbid setting invalid
values of the ‘age’ property:
```typescript ```typescript
class Person { class Person {
...@@ -928,19 +962,22 @@ console.log (p.age) // 0 will be printed out ...@@ -928,19 +962,22 @@ console.log (p.age) // 0 will be printed out
p.age = -42 // Error will be thrown as an attempt to set incorrect age p.age = -42 // Error will be thrown as an attempt to set incorrect age
``` ```
A class may define a getter, a setter or both. A class can define a getter, a setter or both.
## Methods ## Methods
A method is a function that belongs to a class. A method is a function that belongs to a class.
A class can define instance methods, static methods or both. A class can define instance methods, static methods or both.
A static method belongs to the class itself, and can have access to static fields only. A static method belongs to the class itself, and can have access to static
While instance method has access to both static (class) fields and instance fields including private ones of its class. fields only.
A `while` instance method has access to both static (class) fields and
instance fields including private ones of its class.
### Instance Methods ### Instance Methods
Example below illustrates how instanced methods work. The example below illustrates how instanced methods work.
The `calculateArea` method calculates the area of a rectangle by multiplying the height by the width: The `calculateArea` method calculates the area of a rectangle by
multiplying the height by the width:
```typescript ```typescript
class Rectangle { class Rectangle {
...@@ -955,20 +992,21 @@ class Rectangle { ...@@ -955,20 +992,21 @@ class Rectangle {
} }
``` ```
To use an instance method, call it on an instance of the class: To use an instance method, it must be called on an instance of the class:
```typescript ```typescript
let r = new Rectangle(10, 10) let square = new Rectangle(10, 10)
console.log(square.calculateArea()) // output: 100 console.log(square.calculateArea()) // output: 100
``` ```
### Static Methods ### Static Methods
Use the keyword `static` to declare a method as static. Static methods belong to the class itself and have access to static fields only. The keyword `static` is used to declare a method as static. Static methods
belong to the class itself and have access to static fields only.
A static method defines a common behavior of the class as a whole. A static method defines a common behavior of the class as a whole.
All instances have access to static methods. All instances have access to static methods.
To call a static method, use the class name: The class name is used to call a static method:
```typescript ```typescript
class Cl { class Cl {
...@@ -981,7 +1019,8 @@ console.log(Cl.staticMethod()) ...@@ -981,7 +1019,8 @@ console.log(Cl.staticMethod())
### Inheritance ### Inheritance
A class can extend another class (called base class) and implement several interfaces using the following syntax: A class can extend another class (called base class) and implement several
interfaces by using the following syntax:
```typescript ```typescript
class [extends BaseClassName] [implements listOfInterfaces] { class [extends BaseClassName] [implements listOfInterfaces] {
...@@ -989,9 +1028,12 @@ class [extends BaseClassName] [implements listOfInterfaces] { ...@@ -989,9 +1028,12 @@ class [extends BaseClassName] [implements listOfInterfaces] {
} }
``` ```
The extended class inherits fields and methods from the base class, but not constructors, and can add its own fields and methods as well as override methods defined by the base class. The extended class inherits fields and methods from the base class, but
not constructors, and can add its own fields and methods as well as override
methods defined by the base class.
The base class is also called ‘parent class’ or ‘superclass’. The extended class also called ‘derived class’ or ‘subclass’. The base class is also called ‘parent class’ or ‘superclass’.
The extended class also called ‘derived class’ or ‘subclass’.
Example: Example:
...@@ -1011,7 +1053,9 @@ class Employee extends Person { ...@@ -1011,7 +1053,9 @@ class Employee extends Person {
} }
``` ```
A class containing the `implements` clause must implement all methods defined in all listed interfaces, except the methods defined with default implementation. A class containing the `implements` clause must implement all methods
defined in all listed interfaces, except the methods defined with default
implementation.
```typescript ```typescript
interface DateInterface { interface DateInterface {
...@@ -1027,9 +1071,11 @@ class MyDate implements DateInterface { ...@@ -1027,9 +1071,11 @@ class MyDate implements DateInterface {
### Access to Super ### Access to Super
The keyword `super` can be used to access instance fields, instance methods and constructors from the super class. The keyword `super` can be used to access instance fields, instance methods
and constructors from the super class.
It is often used to extend basic functionality of subclass with the required behavior taken from the super class: It is often used to extend basic functionality of subclass with the required
behavior taken from the super class:
```typescript ```typescript
class Rectangle { class Rectangle {
...@@ -1062,9 +1108,11 @@ class FilledRectangle extends Rectangle { ...@@ -1062,9 +1108,11 @@ class FilledRectangle extends Rectangle {
### Override Methods ### Override Methods
A subclass may override implementation of a method defined in its superclass. A subclass can override implementation of a method defined in its superclass.
An overridden method may be marked with the keyword `override`, to improve readability. An overridden method can be marked with the keyword `override` to improve
An overridden method must have the same types of parameters and same or derived return type as the original method. readability.
An overridden method must have the same types of parameters, and same or
derived return type as the original method.
```typescript ```typescript
class Rectangle { class Rectangle {
...@@ -1084,7 +1132,10 @@ class Square extends Rectangle { ...@@ -1084,7 +1132,10 @@ class Square extends Rectangle {
### Method Overload Signatures ### Method Overload Signatures
A method can be specified to can be called in different ways by writing overload signatures. To do so, several method headers are written that have the same name but different signatures, immediately followed by the single implementation method. A method can be specified to be called in different ways by writing overload
signatures. To do so, several method headers that have the same name but
different signatures are written and immediately followed by the single
implementation method.
```typescript ```typescript
class C { class C {
...@@ -1099,13 +1150,15 @@ c.foo() // ok, 1st signature is used ...@@ -1099,13 +1150,15 @@ c.foo() // ok, 1st signature is used
c.foo("aa") // ok, 2nd signature is used c.foo("aa") // ok, 2nd signature is used
``` ```
It is an error if two overload signatures have the same name and identical parameter lists. An error occurs if two overload signatures have the same name and identical
parameter lists.
## Constructors ## Constructors
A class declaration may contain a constructor that is used to initialize object state. A class declaration may contain a constructor that is used to initialize
object state.
Constructor is defined as follows: A constructor is defined as follows:
```typescript ```typescript
constructor ([parameters]) { constructor ([parameters]) {
...@@ -1113,7 +1166,8 @@ constructor ([parameters]) { ...@@ -1113,7 +1166,8 @@ constructor ([parameters]) {
} }
``` ```
If no constructor is defined, then a default constructor with an empty parameter list is created automatically, for example: If no constructor is defined, then a default constructor with an empty
parameter list is created automatically, for example:
```typescript ```typescript
class Point { class Point {
...@@ -1123,11 +1177,13 @@ class Point { ...@@ -1123,11 +1177,13 @@ class Point {
let p = new Point() let p = new Point()
``` ```
In this case the default constructor fills the instance fields with default values for the field types. In this case the default constructor fills the instance fields with
default values for the field types.
### Constructors in Derived Class ### Constructors in Derived Class
The first statement of a constructor body can use the keyword `super` to explicitly call a constructor of the direct superclass. The first statement of a constructor body can use the keyword `super`
to explicitly call a constructor of the direct superclass.
```typescript ```typescript
class Rectangle { class Rectangle {
...@@ -1142,11 +1198,16 @@ class Square extends Rectangle { ...@@ -1142,11 +1198,16 @@ class Square extends Rectangle {
} }
``` ```
If a constructor body does not begin with such an explicit call of a superclass constructor, then the constructor body implicitly begins with a superclass constructor call `super()`. If a constructor body does not begin with such an explicit call of a
superclass constructor, then the constructor body implicitly begins
with a superclass constructor call `super()`.
### Constructor Overload Signatures ### Constructor Overload Signatures
A constructor can be specified to can be called in different ways by writing overload signatures. To do so, several constructor headers are written that have the same name but different signatures, immediately followed by the single implementation constructor. A constructor can be specified to be called in different ways by writing
overload signatures. To do so, several constructor headers that have the
same name but different signatures are written and immediately followed
by the single implementation constructor.
```typescript ```typescript
class C { class C {
...@@ -1160,23 +1221,33 @@ let c1 = new C() // ok, 1st signature is used ...@@ -1160,23 +1221,33 @@ let c1 = new C() // ok, 1st signature is used
let c2 = new C("abc") // ok, 2nd signature is used let c2 = new C("abc") // ok, 2nd signature is used
``` ```
It is an error if two overload signatures have the same name and identical parameter lists. An error occurs if two overload signatures have the same name and
identical parameter lists.
## Visibility Modifiers ## Visibility Modifiers
Both methods and properties of a class can have visibility modifiers. Both methods and properties of a class can have visibility modifiers.
There are several visibility modifiers: `private`, `protected`, There are several visibility modifiers:
`public`, and `internal`. The default visibility is `public`.
`internal` allows to limit visibility within the current package. - `private`,
- `protected`,
- `public`, and
- `internal`.
The default visibility is `public`.
The modifier `internal` allows to limit visibility within
the current package.
### Public Visibility ### Public Visibility
The `public` members (fields, methods, constructors) of a class are visible in any part of the program, where their class is visible. The `public` members (fields, methods, constructors) of a class are
visible in any part of the program, where their class is visible.
### Private Visibility ### Private Visibility
A `private` member cannot be accessed outside the class in which it is declared, for example: A `private` member cannot be accessed outside the class it is declared in,
for example:
```typescript ```typescript
class C { class C {
...@@ -1193,8 +1264,8 @@ c.y = "b" // compile-time error: 'y' is not visible ...@@ -1193,8 +1264,8 @@ c.y = "b" // compile-time error: 'y' is not visible
### Protected Visibility ### Protected Visibility
The `protected` modifier acts much like the `private` modifier, but The modifier `protected` acts much like the modifier `private`, but
`protected` members are also accessible in derived classes, for example: the `protected` members are also accessible in derived classes, for example:
```typescript ```typescript
class Base { class Base {
...@@ -1211,9 +1282,12 @@ class Derived extends Base { ...@@ -1211,9 +1282,12 @@ class Derived extends Base {
## Object Literals ## Object Literals
An object literal is an expression that can be used to create a class instance and provide some initial values. It can be used instead of `new` expression as it is more convenient in some cases. An object literal is an expression that can be used to create a class instance
and provide some initial values. It can be used instead of the expression
`new` as it is more convenient in some cases.
A class composite is written as a comma-separated list of name-value pairs enclosed in ‘{’ and ‘}’. A class composite is written as a comma-separated list of name-value pairs
enclosed in ‘{’ and ‘}’.
```typescript ```typescript
class C { class C {
...@@ -1224,7 +1298,9 @@ class C { ...@@ -1224,7 +1298,9 @@ class C {
let c: C = {n: 42, s: "foo"} let c: C = {n: 42, s: "foo"}
``` ```
Due to static typing of the ArkTS the object literals can be used in context where the class or interface type of the object literal can be inferred as in the example above. Other valid cases: Due to the static typing of the ArkTS, object literals can be used in a
context where the class or interface type of the object literal can be
inferred as in the example above. Other valid cases are illustrated below:
```typescript ```typescript
class C { class C {
...@@ -1244,7 +1320,7 @@ function bar(): C { ...@@ -1244,7 +1320,7 @@ function bar(): C {
} }
``` ```
Type of an array element or a type of a class field also can be used: The type of an array element or of a class field can also be used:
```typescript ```typescript
class C { class C {
...@@ -1254,10 +1330,12 @@ class C { ...@@ -1254,10 +1330,12 @@ class C {
let cc: C[] = [{n: 1, s: "a"}, {n: 2, s: "b"}] let cc: C[] = [{n: 1, s: "a"}, {n: 2, s: "b"}]
``` ```
### Object Literals of the Record Type ### Object Literals of Record Type
The generic Record<K, V> type is used to map the properties of a type
(Key type) to another type (Value type).
The generic Record<K, V> type is used to map the properties of a type (Key type) to another type (Value type). A special form of object literal is used to initialize the value of such type:
A special form of an object literal is used to initialize the value of such type:
```typescript ```typescript
let map: Record<string, number> = { let map: Record<string, number> = {
...@@ -1283,9 +1361,11 @@ let map: Record<string, PersonInfo> = { ...@@ -1283,9 +1361,11 @@ let map: Record<string, PersonInfo> = {
# Interfaces # Interfaces
An interface declaration introduces a new type. Interfaces are a common way of defining contracts between various part of codes. An interface declaration introduces a new type. Interfaces are a common way
of defining contracts between various part of codes.
Interfaces are used to write polymorphic code, which can be applied to any class instances that implement a particular interface. Interfaces are used to write polymorphic code, which can be applied to any
class instances that implement a particular interface.
An interface usually contains properties and method headers. An interface usually contains properties and method headers.
...@@ -1326,9 +1406,11 @@ class Rectangle implements Area { ...@@ -1326,9 +1406,11 @@ class Rectangle implements Area {
## Interface Properties ## Interface Properties
An interface property can be in a form of field, getter, setter or both getter and setter. An interface property can be in a form of field, getter, setter, or both
getter and setter.
A property field is just a shortcut notation of a getter/setter pair, and the following notations are equal: A property field is just a shortcut notation of a getter/setter pair, and
the following notations are equal:
```typescript ```typescript
interface Style { interface Style {
...@@ -1381,28 +1463,31 @@ interface ExtendedStyle extends Style { ...@@ -1381,28 +1463,31 @@ interface ExtendedStyle extends Style {
} }
``` ```
An extended interface contains all properties and methods of the interface it extends and may also add its own properties and methods. An extended interface contains all properties and methods of the
interface it extends, and can also add its own properties and methods.
## Interface Visibility Modifiers ## Interface Visibility Modifiers
Properties and methods are `public`. Properties and methods are `public`.
Only methods with default implementation may be defined as `private`. Only methods with default implementation can be defined as `private`.
# Generic Types and Functions # Generic Types and Functions
Generic types and functions allow creating the code capable to work over a variety of types rather than a single one. Generic types and functions allow creating the code capable to work over a
variety of types rather than a single type.
## Generic Classes and Interfaces ## Generic Classes and Interfaces
A class and an interface can be defined as generics, adding parameters to the type definition, like the type parameter `Element` in the following example: A class and an interface can be defined as generics, adding parameters to the
type definition, like the type parameter `Element` in the following example:
```typescript ```typescript
class Stack<Element> { class Stack<Element> {
public pop(): Element { public pop(): Element {
// ... // ...
} }
public push(e: Element) { public push(e: Element): void {
// ... // ...
} }
} }
...@@ -1415,7 +1500,8 @@ let s = new Stack<string> ...@@ -1415,7 +1500,8 @@ let s = new Stack<string>
s.push("hello") s.push("hello")
``` ```
Compiler ensures type safety while working with generic types and functions. See below Compiler ensures type safety while working with generic types and functions.
See below:
```typescript ```typescript
let s = new Stack<string> let s = new Stack<string>
...@@ -1424,7 +1510,9 @@ s.push(55) // That will be a compile-time error ...@@ -1424,7 +1510,9 @@ s.push(55) // That will be a compile-time error
## Generic Constraints ## Generic Constraints
Type parameters of generic types can be bounded. For example, the `Key` type parameter in the `HashMap<Key, Value>` container must have a hash method, i.e., it should be hashable. Type parameters of generic types can be bounded. For example, the `Key`
type parameter in the `HashMap<Key, Value>` container must have a hash
method, i.e., it must be hashable.
```typescript ```typescript
interface Hashable { interface Hashable {
...@@ -1438,11 +1526,13 @@ class HasMap<Key extends Hashable, Value> { ...@@ -1438,11 +1526,13 @@ class HasMap<Key extends Hashable, Value> {
} }
``` ```
In the above example, the `Key` type extends `Hashable`, and all methods of `Hashable` interface can be called for keys. In the above example, the `Key` type extends `Hashable`, and all methods
of `Hashable` interface can be called for keys.
## Generic Functions ## Generic Functions
Use a generic function to create a more universal code. Consider a function that returns the last element of the array: Use a generic function to create a more universal code. Consider a function
that returns the last element of the array:
```typescript ```typescript
function last(x: number[]): number { function last(x: number[]): number {
...@@ -1451,7 +1541,8 @@ function last(x: number[]): number { ...@@ -1451,7 +1541,8 @@ function last(x: number[]): number {
console.log(last([1, 2, 3])) // output: 3 console.log(last([1, 2, 3])) // output: 3
``` ```
If the same function needs to be defined for any array, define it as generic with a type parameter: If the same function needs to be defined for any array, then define it as
a generic with a type parameter:
```typescript ```typescript
function last<T>(x: T[]): T { function last<T>(x: T[]): T {
...@@ -1461,7 +1552,7 @@ function last<T>(x: T[]): T { ...@@ -1461,7 +1552,7 @@ function last<T>(x: T[]): T {
Now, the function can be used with any array. Now, the function can be used with any array.
In a function call, type argument may be set explicitly or implicitly: In a function call, type argument can be set explicitly or implicitly:
```typescript ```typescript
// Explicit type argument // Explicit type argument
...@@ -1476,7 +1567,8 @@ console.log(last([1, 2, 3])) ...@@ -1476,7 +1567,8 @@ console.log(last([1, 2, 3]))
## Generic Defaults ## Generic Defaults
Type parameters of generic types can have defaults. Type parameters of generic types can have defaults.
It allows not specifying the actual type arguments but using just the generic type name. It allows using just the generic type name instead of specifying the actual
type arguments.
Example below illustrates this for both classes and functions. Example below illustrates this for both classes and functions.
```typescript ```typescript
...@@ -1497,9 +1589,10 @@ foo<number>() ...@@ -1497,9 +1589,10 @@ foo<number>()
# Null Safety # Null Safety
All types in ArkTS by default are non-nullable, so the value of a type cannot be null. All types in ArkTS by default are non-nullable, so the value of a type
cannot be null.
It is similar to TypeScript behavior in strict null checking mode It is similar to TypeScript behavior in strict null checking mode
(`strictNullChecks`), but the rules are stricter, and the there is no `undefined` type in ArkTS. (`strictNullChecks`), but the rules are stricter.
In the example below, all lines cause a compile-time error: In the example below, all lines cause a compile-time error:
...@@ -1522,7 +1615,8 @@ if (x != null) { /* do something */ } ...@@ -1522,7 +1615,8 @@ if (x != null) { /* do something */ }
A postfix operator `!` can be used to assert that its operand is non-null. A postfix operator `!` can be used to assert that its operand is non-null.
If applied to a null value, the operator throws an error. Otherwise, the type of the value is changed from `T | null` to `T`: If applied to a null value, the operator throws an error. Otherwise, the
type of the value is changed from `T | null` to `T`:
```typescript ```typescript
let x: number | null = 1 let x: number | null = 1
...@@ -1533,12 +1627,15 @@ y = x! + 1 // ok ...@@ -1533,12 +1627,15 @@ y = x! + 1 // ok
## Null-Coalescing Operator ## Null-Coalescing Operator
The null-coalescing binary operator `??` checks whether the evaluation of the left-hand-side expression is equal to null. The null-coalescing binary operator `??` checks whether the evaluation
If it is, then the result of the expression is the right-hand-side expression; otherwise, it is the left-hand-side expression. of the left-hand-side expression is equal to null.
If it is, then the result of the expression is the right-hand-side expression;
otherwise, it is the left-hand-side expression.
In other words, `a ?? b` equals the ternary operator `a != null ? a : b`. In other words, `a ?? b` equals the ternary operator `a != null ? a : b`.
In the following example, the method `getNick` returns a nickname if it is set; otherwise, empty string is returned: In the following example, the method `getNick` returns a nickname if it is
set; otherwise, an empty string is returned:
```typescript ```typescript
class Person { class Person {
...@@ -1552,46 +1649,72 @@ class Person { ...@@ -1552,46 +1649,72 @@ class Person {
## Optional Chaining ## Optional Chaining
Optional chaining operator `?.` allows writing code where the evaluation stops of an expression that is partially evaluated to `null`. Optional chaining operator `?.` allows writing code where the evaluation
stops at an expression that is partially evaluated to `null` or `undefined`.
```typescript ```typescript
class Person { class Person {
// ... nick : string | null = null
spouse: Person | null = null spouse ?: Person
nick: string | null = null
getSpouseNick(): string | null { setSpouse(spouse: Person) : void {
this.spouse = spouse
}
getSpouseNick(): string | null | undefined {
return this.spouse?.nick return this.spouse?.nick
} }
constructor(nick: string) {
this.nick = nick
this.spouse = undefined
}
} }
``` ```
**Note**: that the return type of `getSpouseNick` must be `string | null`, as the method may return null. **Note**: the return type of `getSpouseNick` must be `string | null | undefined`, as
the method can return null or undefined.
An optional chain may be of any length and contain any number of `?.` An optional chain can be of any length and contain any number of `?.`
operators. operators.
In the following sample, the output is a person’s spouse nickname if the person has a spouse, and the spouse has a nickname. In the following sample, the output is a person’s spouse nickname if that
person has a spouse, and the spouse has a nickname.
Otherwise, the output is `null`: Otherwise, the output is `undefined`:
```typescript ```typescript
let p: Person = ... class Person {
console.log(p?.spouse?.nick) nick : string | null = null
spouse ?: Person
constructor(nick: string) {
this.nick = nick
this.spouse = undefined
}
}
let p: Person = new Person("Alice")
console.log(p.spouse?.nick) // print: undefined
``` ```
# Modules # Modules
Programs are organized as sets of compilation units or modules. Programs are organized as sets of compilation units or modules.
Each module creates its own scope, i.e., any declarations (variables, functions, classes, etc.) declared in the module are not visible outside that module unless they are explicitly exported. Each module creates its own scope, i.e., any declarations (variables,
functions, classes, etc.) declared in the module are not visible outside
that module unless they are explicitly exported.
Conversely, a variable, function, class, interface, etc. exported from another module must first be imported to a module. Conversely, a variable, function, class, interface, etc. exported from
another module must first be imported to a module.
## Export ## Export
A top-level declaration can be exported by using the keyword `export`. A top-level declaration can be exported by using the keyword `export`.
A declared name that is not exported is considered private and can be used only in the module where it is declared. A declared name that is not exported is considered private and can be used
only in the module where it is declared.
```typescript ```typescript
export class Point { export class Point {
...@@ -1610,16 +1733,21 @@ export function Distance(p1: Point, p2: Point): number { ...@@ -1610,16 +1733,21 @@ export function Distance(p1: Point, p2: Point): number {
## Import ## Import
Import declarations are used to import entities exported from other modules and provide their bindings in the current module. An import declaration consists of two parts: Import declarations are used to import entities exported from other modules
and provide their bindings in the current module. An import declaration
consists of two parts:
* Import path that determines the module to import from; * Import path that determines the module to import from;
* Import bindings that define the set of usable entities in the imported module and the form of use i.e., qualified or unqualified use. * Import bindings that define the set of usable entities in the imported
module, and the form of use (i.e., qualified or unqualified use).
Import bindings may have several forms. Import bindings may have several forms.
Let’s assume a module has the path ‘./utils’ and export entities ‘X’ and ‘Y’. Let’s assume a module has the path ‘./utils’ and export entities ‘X’ and ‘Y’.
An import binding of the form `* as A` binds the name ‘A’, and all entities exported from the module defined by the import path can be accessed by using the qualified name `A.name`: An import binding of the form `* as A` binds the name ‘A’, and all entities
exported from the module defined by the import path can be accessed by using
the qualified name `A.name`:
```typescript ```typescript
import * as Utils from "./utils" import * as Utils from "./utils"
...@@ -1627,7 +1755,8 @@ Utils.X // denotes X from Utils ...@@ -1627,7 +1755,8 @@ Utils.X // denotes X from Utils
Utils.Y // denotes Y from Utils Utils.Y // denotes Y from Utils
``` ```
An import binding of the form `{ ident1, ..., identN }` binds an exported entity with a specified name, which can be used as a simple name: An import binding of the form `{ ident1, ..., identN }` binds an exported
entity with a specified name, which can be used as a simple name:
```typescript ```typescript
import { X, Y } from "./utils" import { X, Y } from "./utils"
...@@ -1635,7 +1764,8 @@ X // denotes X from Utils ...@@ -1635,7 +1764,8 @@ X // denotes X from Utils
Y // denotes Y from Utils Y // denotes Y from Utils
``` ```
If a list of identifiers contains aliasing of the form `ident as alias`, then entity `ident` is bound under the name `alias`: If a list of identifiers contains aliasing of the form `ident as alias`,
then entity `ident` is bound under the name `alias`:
```typescript ```typescript
import { X as Z, Y } from "./utils" import { X as Z, Y } from "./utils"
...@@ -1648,12 +1778,17 @@ X // Compile-time error: 'X' is not visible ...@@ -1648,12 +1778,17 @@ X // Compile-time error: 'X' is not visible
A module can contain any statements at the module level, except `return` ones. A module can contain any statements at the module level, except `return` ones.
If a module contains a `main` function (program entry point) then top-level statements of the module are executed immediately before the body of this function. If a module contains a `main` function (program entry point), then
Otherwise, they are executed before execution of any other function of the module. top-level statements of the module are executed immediately before
the body of this function.
Otherwise, they are executed before execution of any other function
of the module.
## Program Entry Point ## Program Entry Point
An entry point of a program (application) is the top-level `main` function. The `main` function should have either an empty parameter list or a single parameter of `string[]` type. An entry point of a program (application) is the top-level `main` function.
The `main` function must have either an empty parameter list or a single
parameter of `string[]` type.
```typescript ```typescript
function main() { function main() {
...@@ -1664,16 +1799,16 @@ function main() { ...@@ -1664,16 +1799,16 @@ function main() {
# Support for ArkUI # Support for ArkUI
This section demonstrates mechanisms that ArkTS provides for This section demonstrates mechanisms that ArkTS provides for
creating graphical user interface (GUI) programs. The section is based on the creating graphical user interface (GUI) programs. The section is based on
ArkUI declarative framework. ArkUI provides a set of extensions of the standard the ArkUI declarative framework. ArkUI provides a set of extensions of
TypeScript to declaratively describe the GUI of the applications and the interaction the standard TypeScript to declaratively describe the GUI of the applications
between the GUI components. and the interaction between the GUI components.
## ArkUI Example ## ArkUI Example
The following example provides a complete ArkUI-based application as an The following example provides a complete ArkUI-based application as an
illustration of GUI programming capabilities. For more details about ArkUI illustration of GUI programming capabilities. For more details of the
features, please refer to the ArkUI ArkUI features, refer to the ArkUI
[tutorial](arkts-get-started.md). [tutorial](arkts-get-started.md).
```typescript ```typescript
......
...@@ -12,22 +12,24 @@ categories: ...@@ -12,22 +12,24 @@ categories:
2. **Partially supported features**: some minor code refactoring is needed. 2. **Partially supported features**: some minor code refactoring is needed.
Example: The keyword `let` must be used in place of `var` to declare Example: The keyword `let` must be used in place of `var` to declare
variables. Please note that your code will still remain a valid TypeScript code variables. Please note that your code will still remain a valid TypeScript code
after rewriting according to our recipes. after rewriting by our recipes.
3. **Unsupported features**: a greater code refactoring effort can be required. 3. **Unsupported features**: a greater code refactoring effort can be required.
Example: The type `any` is unsupported, and you are to introduce explicit Example: The type `any` is unsupported, and you are to introduce explicit
typing to your code everywhere `any` is used. typing to your code everywhere `any` is used.
PageBreak
# How to Use The Cookbook # How to Use The Cookbook
The main goal of this cookbook is to provide recipes for all partially The main goal of this cookbook is to provide recipes for all partially
supported features and explicitly list all unsupported features. supported features and explicitly list all unsupported features.
The document is built on the feature-by-feature basis, and if you do not find The document is built on the feature-by-feature basis, and if you do not
some feature, you can safely consider it **supported**. Otherwise, a recipe find some feature, then you can safely consider it **supported**. Otherwise,
will give you a suggestion on how to rewrite your code and work around an a recipe will give you a suggestion on how to rewrite your code and work
unsupported case. around an unsupported case.
## Recipe explained ## Recipe Explained
The original TypeScript code containing the keyword `var`: The original TypeScript code containing the keyword `var`:
...@@ -38,7 +40,7 @@ function addTen(x: number): number { ...@@ -38,7 +40,7 @@ function addTen(x: number): number {
} }
``` ```
This code must be rewritten as follows: must be rewritten as follows:
```typescript ```typescript
// Important! This is still valid TypeScript. // Important! This is still valid TypeScript.
...@@ -50,40 +52,40 @@ function addTen(x: number): number { ...@@ -50,40 +52,40 @@ function addTen(x: number): number {
## Status of Unsupported Features ## Status of Unsupported Features
Currently unsupported are mainly the features which Currently unsupported are mainly the features which:
- relate to dynamic typing that degrades runtime performance, or - relate to dynamic typing that degrades runtime performance, or
- require extra support in the compiler, thus degrading project build time. - require extra support in the compiler, thus degrading project build time.
However, the ArkTS team reserves the right to reconsider the list and However, the ArkTS team reserves the right to reconsider the list and
**shrink** it in the future releases based on the feedback from the developers **shrink** it in the future releases based on the feedback from the developers,
and more real-world data experiments. and on more real-world data experiments.
PageBreak
# Recipes Summarized # Recipes Summarized
This documents provides an informal summary of TypeScript features that ArkTS either This document provides an informal summary of TypeScript features that ArkTS either
does not support or supports with limitations. For the full list, with more can support with limitations, or cannot support. See [Recipes](#recipes) for the
detailed code examples and workaround suggestions, please see full list with more detailed code examples and workaround suggestions.
[this section](#recipes).
## Static typing is enforced ## Static Typing is Enforced
ArkTS was designed with following goals in mind: ArkTS was designed with the following goals in mind:
- It should be easy for developers to read and understand ArkTS programs, - ArkTS programs must be easy for developers to read and understand because
because the code is read more often than written; the code is read more often than written;
- ArkTS should execute fast with as little power consumption as possible, - ArkTS must execute fast and consume as little power as possible because
which is critical for mobile devices which ArkTS targets. it is particularly critical on mobile devices which ArkTS targets.
Static typing is one of the most important features of ArkTS, which helps One of the most important features of ArkTS that helps achieving both goals
achieve both goals. Indeed, if your program is statically typed, i.e. all is static typing. Indeed, if a program is statically typed, i.e. all types
types are known at the compile time, it’s much easier to understand which data are known at compile time, then it is much easier to understand what data
structures are used in the code. At the same time, since all types are known structures are used in the code. That all types are known before the program
before the program actually runs, code correctness can be verified by the actually runs results in the compiler to verify code correctness, thus
compiler, which eliminates many runtime type checks and improves the eliminating many runtime type checks and improving performance.
performance.
Therefore, it was decided to prohibit usage of the type `any`. Therefore, the usage of the type `any` in ArkTS is prohibited.
### Example ### Example
...@@ -112,26 +114,27 @@ if (!res.succeeded()) { ...@@ -112,26 +114,27 @@ if (!res.succeeded()) {
} }
``` ```
### Rationale and impact ### Rationale and Impact
Our research and experiments let us conclude that this feature is already Our research and experiments let us conclude that `any` is already not welcome
not welcome in the modern TypeScript. According to our measurements, it is used in TypeScript. According to our measurements, `any` is used in approximately 1% of
in approximately 1% of TypeScript code bases. Moreover, code linters (e.g., ESLint) TypeScript codebases. Moreover, today’s code linters (e.g., ESLint) include a set
already include a set of rules that prohibit usage of `any`. Thus, although of rules that prohibit the usage of `any`.
prohibiting `any` requires code refactoring, we consider it a low-effort
change with the high impact result.
## Changing object layout in runtime is prohibited Prohibiting `any` results in a strong positive impact on performance at the
cost of low-effort code refactoring.
To achieve maximum performance benefits, ArkTS requires that layout of objects ## Changing Object Layout in Runtime Is Prohibited
does not change during program execution. In other words, it is prohibited to:
- add new properties or methods to the objects; To achieve maximum performance benefits, ArkTS requires the layout of objects
- delete existing properties or methods from the objects; to not change during program execution. In other words, it is prohibited to:
- add new properties or methods to objects;
- delete existing properties or methods from objects;
- assign values of arbitrary types to object properties. - assign values of arbitrary types to object properties.
It’s worth noticing that many such operations are already prohibited by the TypeScript It is noteworthy that many such operations are already prohibited by the TypeScript
compiler. However, it still can be “tricked” by e.g. `as any` casts, wchich compiler. However, it still can be “tricked”, e.g., by `as any` casts that
ArkTS does not support (see the detailed example below). ArkTS does not support (see the detailed example below).
### Example ### Example
...@@ -193,29 +196,27 @@ let p6 = new Point(6.0, 6.0) ...@@ -193,29 +196,27 @@ let p6 = new Point(6.0, 6.0)
console.log("Distance between p5 and p6: " + distance(p5, p6)) console.log("Distance between p5 and p6: " + distance(p5, p6))
``` ```
### Rationale and impact ### Rationale and Impact
Unpredictable changing of object layout contradicts both good readability and Unpredictable changing of object layout contradicts both good readability and
good performance of the code. Indeed, having class definition at one place and good performance of code. Indeed, having class definition at one place and
modifying actual object layout elsewhere is confusing and error-prone from the modifying actual object layout elsewhere is confusing and error-prone from the
developer’s point of view. Additionally, it requires extra runtime support, developer’s point of view. It opposes the idea of static typing (why adding
which brings undesired execution overhead. Moreover, it contradicts the idea of or removing additional properties if typing is to be as explicit as possible?)
static typing. If we want to make typing as explicit as possible, why would we and requires extra runtime support that causes undesired execution overhead.
need to add or remove additional properties?
At the same time, according to our observations and experiments, this feature According to our observations and experiments, this feature is already not
is already not welcome in the modern TypeScript. It is used in the marginal number of welcome in TypeScript: it is used in a marginal number of real-world projects,
cases in real-world projects and state of the art linters have rules to and state-of-the-art linters have rules to prohibit its usage.
prohibit its usage.
Thus, we conclude that prohibiting runtime changes to objects’ layout results We conclude that prohibiting runtime changes to object layouts results in a
in low-effort refactoring with the high positive impact on performance. strong positive impact on performance at the cost of low-effort refactoring.
## Semantics of operators is restricted ## Semantics of Operators Is Restricted
To achieve better performance and encourage developers write clearer code, To achieve better performance and encourage developers write clearer code,
ArkTS restricts semantics of some operators. A couple of examples are given ArkTS restricts the semantics of some operators. A couple of examples are
below, and the full list of restrictions is outlined [here](#recipes). given below, and the full list of restrictions is outlined in [Recipes](#recipes).
### Example ### Example
...@@ -229,24 +230,23 @@ let c2 : C = new C() ...@@ -229,24 +230,23 @@ let c2 : C = new C()
console.log(c1 + c2) // Compile-time error console.log(c1 + c2) // Compile-time error
``` ```
### Rationale and impact ### Rationale and Impact
Overloading language operators with extra semantics complicates language Loading language operators with extra semantics complicates the language
specification and makes developers remember about all possible corner cases specification, and forces developers to remember all possible corner cases with
and their handling rules. Besides, in certain cases it incurs some runtime appropriate handling rules. Besides, in certain cases it causes some undesired
overhead, which is undesired. runtime overhead.
At the same time, according to our observations and experiments, this feature At the same time, according to our observations and experiments, this feature
is not popular in the modern TypeScript. It is used in less than 1% of real-world is not popular in TypeScript. It is used in less than 1% of real-world codebases,
code bases. Besides, such cases are very easy to refactor. and such cases are easy to refactor.
Thus, although restricting semantics of operators requires changing the code, Restricting the operator semantics results in a clearer and more performant
this is a low-effort change which results in a clearer and more performant code. at the cost of low-effort changes in code.
## Structural typing is not supported (yet) ## Structural Typing Is Not Supported (Yet)
Let’s consider a situation when two unrelated classes `T` and `U` have the Assuming that two unrelated classes `T` and `U` have the same public API:
same public API:
```typescript ```typescript
class T { class T {
...@@ -284,31 +284,34 @@ let t : T = new T() ...@@ -284,31 +284,34 @@ let t : T = new T()
greeter(t) // Is this allowed? greeter(t) // Is this allowed?
``` ```
Or, in other words, which approach will we take: In other words, which approach will we take:
- `T` and `U` are not related by inheritance or any common interface, but - `T` and `U` are not related by inheritance or any common interface, but
since they have the same public API, they are “somewhat equivalent”, so the they are “somewhat equivalent” since they have the same public API, and so
answer to both questions above is “yes”; the answer to both questions above is “yes”;
- `T` and `U` are not related by inheritance or any common interface, and - `T` and `U` are not related by inheritance or any common interface, and
should always be considered as totally different types, so the always must be considered as totally different types, so that the answer to
answer to both questions above is “no”. both questions above is “no”.
Languages that take the first approach are said to support structural typing, The languages that take the first approach are said to support structural
while languages that take the second approach do not support it. Currently, typing, while the languages that take the second approach do not support it.
TypeScript supports structural typing, and ArkTS does not. Currently, TypeScript supports structural typing, and ArkTS does not.
It is debatable if structural typing helps produce clear and It is debatable whether or not structural typing helps to produce code that
understandable code, arguments can be found both for and against it. is clearer and more understandable, and both *pro* and *contra* arguments can
Moreover, structural typing does not harm program performance (at least in some be found. Moreover, structural typing does not harm program performance (at
cases). Why is it not supported then? least in some cases). Why not support it then?
The answer is that support for structural typing is a major feature which needs The answer is that supporting structural typing is a major feature that needs
lots of consideration and careful implementation in language specification, a lot of consideration and careful implementation in language specification,
compiler and runtime. Safe and efficient implementation requires that other compiler and runtime. As safe and efficient implementation requires taking
aspects (static typing, restrictions on changing object layout) are also other aspects (static typing, restrictions on changing object layout) into
taken into account. That’s why support for this feature is postponed. The team account, the support to this feature is postponed.
will be ready to reconsider based on real-world scenarios and feedback. More
cases and suggested workarounds can be found in [Recipes](#recipes). The ArkTS team is ready to reconsider based on real-world scenarios and
feedback. More cases and suggested workarounds can be found in [Recipes](#recipes).
PageBreak
# Recipes # Recipes
...@@ -335,9 +338,9 @@ console.log(x[2]) ...@@ -335,9 +338,9 @@ console.log(x[2])
```typescript ```typescript
class X { class X {
public name: number public name: number = 0
} }
let x = {name: 1} let x:X = {name: 1}
console.log(x.name) console.log(x.name)
let y = [1, 2, 3] let y = [1, 2, 3]
...@@ -372,7 +375,7 @@ console.log(z.get(2)) ...@@ -372,7 +375,7 @@ console.log(z.get(2))
TypeScript has `Symbol()` API, which can be used among other things to generate TypeScript has `Symbol()` API, which can be used among other things to generate
unique property names at runtime. ArkTS does not support `Symbol()` API unique property names at runtime. ArkTS does not support `Symbol()` API
because its most popular use cases make no sense in the statically typed because its most popular use cases make no sense in the statically typed
environment. In particular, the object layout is defined at compile time environment. In particular, the object layout is defined at compile time,
and cannot be changed at runtime. and cannot be changed at runtime.
**TypeScript** **TypeScript**
...@@ -388,7 +391,7 @@ let o = { ...@@ -388,7 +391,7 @@ let o = {
```typescript ```typescript
class SomeClass { class SomeClass {
public someProperty : string public someProperty : string = ""
} }
let o = new SomeClass() let o = new SomeClass()
``` ```
...@@ -410,15 +413,18 @@ let o = new SomeClass() ...@@ -410,15 +413,18 @@ let o = new SomeClass()
**Severity: error** **Severity: error**
ArkTS does not private identifiers started with `#` symbol, use `private` ArkTS does not use private identifiers starting with the symbol `#`. Use
keyword instead. the keyword `private` instead.
**TypeScript** **TypeScript**
```typescript ```typescript
/*
* Such notation for private fields is not supported:
class C { class C {
#foo: number = 42 #foo: number = 42
} }
*/
``` ```
**ArkTS** **ArkTS**
...@@ -458,7 +464,7 @@ type T = number[] // X is not allowed here to avoid name collisions ...@@ -458,7 +464,7 @@ type T = number[] // X is not allowed here to avoid name collisions
**Severity: error** **Severity: error**
ArkTS does not support `var`, always use `let` instead. ArkTS does not support `var`. Use `let` instead.
**TypeScript** **TypeScript**
...@@ -507,59 +513,40 @@ scoped_var = 5 ...@@ -507,59 +513,40 @@ scoped_var = 5
scoped_let = 5 // Compile-time error scoped_let = 5 // Compile-time error
``` ```
## Recipe: Use explicit types instead of `any`, `undefined`, `unknown` ## Recipe: Use explicit types instead of `any`, `unknown`
**Rule `arkts-no-any-undefined-unknown`** **Rule `arkts-no-any-unknown`**
**Severity: error** **Severity: error**
ArkTS does not support `any`, `undefined`, and `unknown` types. ArkTS does not support the types `any` and `unknown`. Specify
Specify types explicitly. types explicitly.
**TypeScript** **TypeScript**
```typescript ```typescript
var x let value1 : any
console.log(x) // undefined value1 = true
value1 = 42
var y: any let value2 : unknown
console.log(y) // undefined value2 = true
value2 = 42
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
// All variables should have their types specified explicitly: let value_b: boolean = true // OR: let value_b = true
let x: Object = {} let value_n: number = 42 // OR: let value_n = 42
console.log(x) // {} let value_o1: Object = true
let value_o2: Object = 42
``` ```
**See also** **See also**
* Recipe: Use Object[] instead of tuples * Recipe: Use Object[] instead of tuples
* Recipe: Strict type checking is enforced
## Recipe: `bigint` is not a builtin type, suffix `n` for numeric literals is not supported
**Rule `arkts-no-n-suffix`**
**Severity: error**
ArkTS supports `bigint` as a part of the standard library, not as a builtin
type. `n` suffix for numeric literals is not supported, `BigInt` factory
function can be used to produce values of `bigint` type.
**TypeScript**
```typescript
let a: bigint = 1n
```
**ArkTS**
```typescript
let a = BigInt(1)
let b: bigint = BigInt(2)
```
## Recipe: Use `Object[]` instead of tuples ## Recipe: Use `Object[]` instead of tuples
...@@ -567,7 +554,7 @@ let b: bigint = BigInt(2) ...@@ -567,7 +554,7 @@ let b: bigint = BigInt(2)
**Severity: error** **Severity: error**
Currently, ArkTS does not support tuples. You can use arrays of `Object` Currently, ArkTS does not support tuples. Use arrays of `Object`
(`Object[]`) to emulate tuples. (`Object[]`) to emulate tuples.
**TypeScript** **TypeScript**
...@@ -679,8 +666,8 @@ function fn(s: string): SomeObject { ...@@ -679,8 +666,8 @@ function fn(s: string): SomeObject {
**Severity: error** **Severity: error**
ArkTS does not allow to have sevaral static block for class initialization, ArkTS does not allow having sevaral static blocks for class initialization.
combine static blocks statements to the one static block. Combine static block statements into one static block.
**TypeScript** **TypeScript**
...@@ -716,7 +703,7 @@ class C { ...@@ -716,7 +703,7 @@ class C {
**Severity: error** **Severity: error**
ArkTS does not allow indexed signatures, use arrays instead. ArkTS does not allow indexed signatures. Use arrays instead.
**TypeScript** **TypeScript**
...@@ -738,7 +725,7 @@ const secondItem = myArray[1] ...@@ -738,7 +725,7 @@ const secondItem = myArray[1]
```typescript ```typescript
class X { class X {
public f: string[] public f: string[] = []
} }
let myArray: X = new X() let myArray: X = new X()
...@@ -751,8 +738,8 @@ const secondItem = myArray.f[1] ...@@ -751,8 +738,8 @@ const secondItem = myArray.f[1]
**Severity: error** **Severity: error**
Currently, ArkTS does not support intersection types. You can use inheritance Currently, ArkTS does not support intersection types. Use inheritance
as a work-around. as a workaround.
**TypeScript** **TypeScript**
...@@ -764,7 +751,7 @@ interface Identity { ...@@ -764,7 +751,7 @@ interface Identity {
interface Contact { interface Contact {
email: string email: string
phone: string phoneNumber: string
} }
type Employee = Identity & Contact type Employee = Identity & Contact
...@@ -780,15 +767,15 @@ interface Identity { ...@@ -780,15 +767,15 @@ interface Identity {
interface Contact { interface Contact {
email: string email: string
phone: string phoneNumber: string
} }
interface Employee extends Identity, Contact {} interface Employee extends Identity, Contact {}
``` ```
## Recipe: Returning `this` type is not supported ## Recipe: Type notation using `this` is not supported
**Rule `arkts-no-this-as-return-type`** **Rule `arkts-no-typing-with-this`**
**Severity: error** **Severity: error**
...@@ -800,6 +787,14 @@ ArkTS does not support the returning `this` type. Use explicit type instead. ...@@ -800,6 +787,14 @@ ArkTS does not support the returning `this` type. Use explicit type instead.
interface ListItem { interface ListItem {
getHead(): this getHead(): this
} }
class C {
n: number = 0
m(c: this) {
console.log(c)
}
}
``` ```
**ArkTS** **ArkTS**
...@@ -808,6 +803,14 @@ interface ListItem { ...@@ -808,6 +803,14 @@ interface ListItem {
interface ListItem { interface ListItem {
getHead(): ListItem getHead(): ListItem
} }
class C {
n: number = 0
m(c: C) {
console.log(c)
}
}
``` ```
## Recipe: Conditional types are not supported ## Recipe: Conditional types are not supported
...@@ -817,8 +820,8 @@ interface ListItem { ...@@ -817,8 +820,8 @@ interface ListItem {
**Severity: error** **Severity: error**
ArkTS does not support conditional type aliases. Introduce a new type with ArkTS does not support conditional type aliases. Introduce a new type with
constraints explicitly or rewrite logic with use of `Object`. `infer` constraints explicitly, or rewrite logic using `Object`. The keyword
keyword is not supported. `infer` is not supported.
**TypeScript** **TypeScript**
...@@ -842,44 +845,6 @@ type X2<T> = Object ...@@ -842,44 +845,6 @@ type X2<T> = Object
type YI<Item, T extends Array<Item>> = Item type YI<Item, T extends Array<Item>> = Item
``` ```
## Recipe: Optional parameters are not supported for primitive types
**Rule `arkts-no-opt-params`**
**Severity: error**
ArkTS does not support optional parameters of primitive types.
You can use default parameter values or reference types. For reference types,
non-specified optional parameter is set to `null`.
**TypeScript**
```typescript
// x is an optional parameter:
function f(x?: number) {
console.log(x) // log undefined or number
}
// x is a required parameter with the default value:
function g(x: number = 1) {
console.log(x)
}
```
**ArkTS**
```typescript
// You can use reference type (will be set to null if missing):
function f(x?: Number) {
console.log(x) // log null or some number
}
// You can use a required parameter with the default value:
function g(x: number = 1) {
console.log(x)
}
```
## Recipe: Declaring fields in `constructor` is not supported ## Recipe: Declaring fields in `constructor` is not supported
**Rule `arkts-no-ctor-prop-decls`** **Rule `arkts-no-ctor-prop-decls`**
...@@ -887,7 +852,7 @@ function g(x: number = 1) { ...@@ -887,7 +852,7 @@ function g(x: number = 1) {
**Severity: error** **Severity: error**
ArkTS does not support declaring class fields in the `constructor`. ArkTS does not support declaring class fields in the `constructor`.
You must declare them inside the `class` declaration instead. Declare class fields inside the `class` declaration instead.
**TypeScript** **TypeScript**
...@@ -929,7 +894,7 @@ class Person { ...@@ -929,7 +894,7 @@ class Person {
} }
``` ```
## Recipe: Construct signatures not supported in interfaces ## Recipe: Construct signatures are not supported in interfaces
**Rule `arkts-no-ctor-signatures-iface`** **Rule `arkts-no-ctor-signatures-iface`**
...@@ -1019,11 +984,11 @@ let x = p.x ...@@ -1019,11 +984,11 @@ let x = p.x
**Severity: error** **Severity: error**
Currently, ArkTS does not support structural identity, i.e., the compiler Currently, ArkTS does not support structural identity, i.e., the compiler
cannot compare two types’ public APIs and decide whether such types are cannot compare public APIs of two types and decide whether such types are
identical. Use other mechanisms (inheritance, interfaces or type aliases) identical. Use other mechanisms (inheritance, interfaces or type aliases)
instead. instead.
For the examples below, types `X` and `Y` are equivalent (interchangeble) In the examples below, types `X` and `Y` are equivalent (interchangeble)
in TypeScript, while in ArkTS they are not. in TypeScript, while in ArkTS they are not.
**TypeScript** **TypeScript**
...@@ -1061,7 +1026,7 @@ type Y = X // Y is equal to X ...@@ -1061,7 +1026,7 @@ type Y = X // Y is equal to X
**Severity: error** **Severity: error**
Currently, ArkTS does not check structural equivalence for type inference, Currently, ArkTS does not check structural equivalence for type inference,
i.e., the compiler cannot compare two types’ public APIs and decide whether i.e., the compiler cannot compare public APIs of two types and decide whether
such types are identical. Use other mechanisms (inheritance or interfaces) such types are identical. Use other mechanisms (inheritance or interfaces)
instead. instead.
...@@ -1135,8 +1100,8 @@ x = y // ok, X is the super class of Y ...@@ -1135,8 +1100,8 @@ x = y // ok, X is the super class of Y
**Severity: error** **Severity: error**
Currently, ArkTS does not check structural equivalence when checking if types Currently, ArkTS does not check structural equivalence when checking if types
are assignable to each other, i.e., the compiler cannot compare two types’ are assignable to each other, i.e., the compiler cannot compare public APIs of
public APIs and decide whether such types are identical. Use other mechanisms two types and decide whether such types are identical. Use other mechanisms
(inheritance or interfaces) instead. (inheritance or interfaces) instead.
**TypeScript** **TypeScript**
...@@ -1208,56 +1173,6 @@ x = y // ok, both are of the same type ...@@ -1208,56 +1173,6 @@ x = y // ok, both are of the same type
* Recipe: Structural typing is not supported for subtyping / supertyping * Recipe: Structural typing is not supported for subtyping / supertyping
* Recipe: Structural typing is not supported for type inference * Recipe: Structural typing is not supported for type inference
## Recipe: Optional properties are not supported for primitive types
**Rule `arkts-no-opt-props`**
**Severity: error**
ArkTS does not support optional properties of primitive types. You can use
properties with default values or reference types. For reference types,
non-specified optional property is set to `null`. This rule applies both to
classes and interfaces.
**TypeScript**
```typescript
class CompilerOptions {
strict?: boolean
sourcePath?: string
targetPath?: string
}
let options: CompilerOptions = {
strict: true,
sourcePath: "./src"
}
if (options.targetPath == undefined) {
// Some logic
}
```
**ArkTS**
```typescript
class CompilerOptions {
strict: boolean = false
sourcePath: string = ""
targetPath?: string
}
let options: CompilerOptions = {
strict: true,
sourcePath: "./src"
// targetPath is implicitly set to null
}
if (options.targetPath == null) {
// Some logic
}
```
## Recipe: Type inference in case of generic function calls is limited ## Recipe: Type inference in case of generic function calls is limited
**Rule `arkts-no-inferred-generic-params`** **Rule `arkts-no-inferred-generic-params`**
...@@ -1265,8 +1180,8 @@ if (options.targetPath == null) { ...@@ -1265,8 +1180,8 @@ if (options.targetPath == null) {
**Severity: error** **Severity: error**
ArkTS allows to omit generic type parameters if it is possible to infer ArkTS allows to omit generic type parameters if it is possible to infer
the concrete types from the parameters passed to the function. Otherwise a the concrete types from the parameters passed to the function. A compile-time
compile-time error occurs. In particular, inference of generic type parameters error occurs otherwise. In particular, inference of generic type parameters
based only on function return types is prohibited. based only on function return types is prohibited.
**TypeScript** **TypeScript**
...@@ -1282,7 +1197,7 @@ let y = choose("10", 20) // Compile-time error ...@@ -1282,7 +1197,7 @@ let y = choose("10", 20) // Compile-time error
function greet<T>(): T { function greet<T>(): T {
return "Hello" as T return "Hello" as T
} }
let z = greet() // Type of x is inferred as "unknown" let z = greet() // Type of T is inferred as "unknown"
``` ```
**ArkTS** **ArkTS**
...@@ -1308,7 +1223,7 @@ let z = greet<string>() ...@@ -1308,7 +1223,7 @@ let z = greet<string>()
**Severity: error** **Severity: error**
Currently, ArkTS does not support structural typing, i.e., the compiler cannot Currently, ArkTS does not support structural typing, i.e., the compiler cannot
compare two types’ public APIs and decide whether such types are identical. compare public APIs of two types and decide whether such types are identical.
Use inheritance and interfaces to specify the relation between the types Use inheritance and interfaces to specify the relation between the types
explicitly. explicitly.
...@@ -1402,8 +1317,8 @@ bar(new Y(2)) ...@@ -1402,8 +1317,8 @@ bar(new Y(2))
**Severity: error** **Severity: error**
Currently, ArkTS does not support RegExp literals. Use library call with string Currently, ArkTS does not support RegExp literals. Use library call with
literals instead. string literals instead.
**TypeScript** **TypeScript**
...@@ -1424,9 +1339,9 @@ let regex: RegExp = new RegExp("/bc*d/") ...@@ -1424,9 +1339,9 @@ let regex: RegExp = new RegExp("/bc*d/")
**Severity: error** **Severity: error**
ArkTS supports usage of object literals if the compiler can infer to what ArkTS supports usage of object literals if the compiler can infer to what
classes or interfaces such literals correspond to. Otherwise, a compile-time classes or interfaces such literals correspond to. A compile-time error
error occurs. Specifically, using literals to initialize classes and interfaces occurs otherwise. Using literals to initialize classes and interfaces is
is not supported in following contexts: specifically not supported in the following contexts:
* Initialization of anything that has `any`, `Object`, or `object` type * Initialization of anything that has `any`, `Object`, or `object` type
* Initialization of classes or interfaces with methods * Initialization of classes or interfaces with methods
...@@ -1579,8 +1494,8 @@ type S = Set<{x: number, y: number}> ...@@ -1579,8 +1494,8 @@ type S = Set<{x: number, y: number}>
```typescript ```typescript
class O { class O {
x: number x: number = 0
y: number y: number = 0
} }
let o: O = {x: 2, y: 3} let o: O = {x: 2, y: 3}
...@@ -1600,8 +1515,8 @@ type S = Set<O> ...@@ -1600,8 +1515,8 @@ type S = Set<O>
**Severity: error** **Severity: error**
Basically, ArkTS infers the type of an array literal as a union type of its Basically, ArkTS infers the type of an array literal as a union type of its
contents. But if there is at least one element with a non-inferrable type contents. However, a compile-time error occurs if there is at least one
(e.g. untyped object literal), a compile-time error occurs. element with a non-inferrable type (e.g. untyped object literal).
**TypeScript** **TypeScript**
...@@ -1638,7 +1553,8 @@ to be explicitly specified. ...@@ -1638,7 +1553,8 @@ to be explicitly specified.
**TypeScript** **TypeScript**
```typescript ```typescript
let f = (s) => { // type any is assumed // Compile-time error only with noImplicitAny:
let f = (s /* type any is assumed */) => {
console.log(s) console.log(s)
} }
``` ```
...@@ -1658,8 +1574,8 @@ let f = (s: string) => { ...@@ -1658,8 +1574,8 @@ let f = (s: string) => {
**Severity: error** **Severity: error**
ArkTS does not support function expressions, use arrow functions instead ArkTS does not support function expressions. Use arrow functions instead
to be explicitly specified. to specify explicitly.
**TypeScript** **TypeScript**
...@@ -1710,19 +1626,19 @@ generic_func<String>("string") ...@@ -1710,19 +1626,19 @@ generic_func<String>("string")
**Severity: error** **Severity: error**
ArkTS does not support class literals. A new named class type must be ArkTS does not support class literals. Introduce new named class types
introduced explicitly. explicitly.
**TypeScript** **TypeScript**
```typescript ```typescript
const Rectangle = class { const Rectangle = class {
constructor(height: number, width: number) { constructor(height: number, width: number) {
this.heigth = height this.height = height
this.width = width this.width = width
} }
heigth height
width width
} }
...@@ -1734,11 +1650,11 @@ const rectangle = new Rectangle(0.0, 0.0) ...@@ -1734,11 +1650,11 @@ const rectangle = new Rectangle(0.0, 0.0)
```typescript ```typescript
class Rectangle { class Rectangle {
constructor(height: number, width: number) { constructor(height: number, width: number) {
this.heigth = height this.height = height
this.width = width this.width = width
} }
heigth: number height: number
width: number width: number
} }
...@@ -1770,7 +1686,7 @@ class C1 implements C { ...@@ -1770,7 +1686,7 @@ class C1 implements C {
```typescript ```typescript
interface C { interface C {
foo() foo(): void
} }
class C1 implements C { class C1 implements C {
...@@ -1786,7 +1702,7 @@ class C1 implements C { ...@@ -1786,7 +1702,7 @@ class C1 implements C {
ArkTS supports accessing only those class properties that are either declared ArkTS supports accessing only those class properties that are either declared
in the class, or accessible via inheritance. Accessing any other properties is in the class, or accessible via inheritance. Accessing any other properties is
prohibited and causes compile-time errors. Use proper types to check property prohibited, and causes compile-time errors. Use proper types to check property
existence during compilation. existence during compilation.
**TypeScript** **TypeScript**
...@@ -1796,7 +1712,7 @@ let person = {name: "Bob", isEmployee: true} ...@@ -1796,7 +1712,7 @@ let person = {name: "Bob", isEmployee: true}
let n = person["name"] let n = person["name"]
let e = person["isEmployee"] let e = person["isEmployee"]
let s = person["office"] // undefined let s = person["office"] // Compile-time error only with noImplicitAny
``` ```
**ArkTS** **ArkTS**
...@@ -1835,10 +1751,13 @@ let s = person.office // Compile-time error ...@@ -1835,10 +1751,13 @@ let s = person.office // Compile-time error
**Severity: error** **Severity: error**
ArkTS supports `as` keyword as the only syntax for type casts. ArkTS supports the keyword `as` as the only syntax for type casts.
Incorrect cast causes a compile-time error or runtime `ClassCastException`. Incorrect cast causes a compile-time error or runtime `ClassCastException`.
`<type>` syntax for type casts is not supported. `<type>` syntax for type casts is not supported.
Use the expression `new ...` instead of `as` if a **primitive** type
(e.g., a `number` or a `boolean`) must be cast to the reference type.
**TypeScript** **TypeScript**
```typescript ```typescript
...@@ -1858,6 +1777,14 @@ let c2 = createShape() as Circle ...@@ -1858,6 +1777,14 @@ let c2 = createShape() as Circle
// nor during runtime if cast is wrong: // nor during runtime if cast is wrong:
let c3 = createShape() as Square let c3 = createShape() as Square
console.log(c3.y) // undefined console.log(c3.y) // undefined
// Important corner case for casting primitives to the boxed counterparts:
// The left operand is not properly boxed here in in runtime
// because "as" has no runtime effect in TypeScript
let e1 = (5.0 as Number) instanceof Number // false
// Number object is created and instanceof works as expected:
let e2 = (new Number(5.0)) instanceof Number // true
``` ```
**ArkTS** **ArkTS**
...@@ -1875,6 +1802,9 @@ let c2 = createShape() as Circle ...@@ -1875,6 +1802,9 @@ let c2 = createShape() as Circle
// ClassCastException during runtime is thrown: // ClassCastException during runtime is thrown:
let c3 = createShape() as Square let c3 = createShape() as Square
// Number object is created and instanceof works as expected:
let e2 = (new Number(5.0)) instanceof Number // true
``` ```
## Recipe: JSX expressions are not supported ## Recipe: JSX expressions are not supported
...@@ -1906,38 +1836,7 @@ let d = -"5" // -5 as number ...@@ -1906,38 +1836,7 @@ let d = -"5" // -5 as number
let e = ~5 // -6 as number let e = ~5 // -6 as number
let f = ~"5" // -6 as number let f = ~"5" // -6 as number
let g = +"string" // NaN as number let g = +"string" // NaN as number
```
**ArkTS**
```typescript
let a = +5 // 5 as number
let b = +"5" // Compile-time error
let c = -5 // -5 as number
let d = -"5" // Compile-time error
let e = ~5 // -6 as number
let f = ~"5" // Compile-time error
let g = +"string" // Compile-time error
```
**See also**
* Recipe: Binary operators \*, /, %, -, <<, >>, >>>, &, ^ and | work only on numeric types
* Recipe: Binary + operator supports implicit casts only for numbers and strings
## Recipe: Unary `+` cannot be used for casting to `number`
**Rule `arkts-no-unary-plus-cast`**
**Severity: error**
ArkTS does not support casting from any type to a numeric type
by using the unary `+` operator, which can be applied only to
numeric types.
**TypeScript**
```typescript
function returnTen(): string { function returnTen(): string {
return "-10" return "-10"
} }
...@@ -1946,13 +1845,21 @@ function returnString(): string { ...@@ -1946,13 +1845,21 @@ function returnString(): string {
return "string" return "string"
} }
let a = +returnTen() // -10 as number let x = +returnTen() // -10 as number
let b = +returnString() // NaN let y = +returnString() // NaN
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
let a = +5 // 5 as number
let b = +"5" // Compile-time error
let c = -5 // -5 as number
let d = -"5" // Compile-time error
let e = ~5 // -6 as number
let f = ~"5" // Compile-time error
let g = +"string" // Compile-time error
function returnTen(): string { function returnTen(): string {
return "-10" return "-10"
} }
...@@ -1961,16 +1868,10 @@ function returnString(): string { ...@@ -1961,16 +1868,10 @@ function returnString(): string {
return "string" return "string"
} }
let a = +returnTen() // Compile-time error let x = +returnTen() // Compile-time error
let b = +returnString() // Compile-time error let y = +returnString() // Compile-time error
``` ```
**See also**
* Recipe: Unary operators +, - and ~ work only on numbers
* Recipe: Binary operators \*, /, %, -, <<, >>, >>>, &, ^ and | work only on numeric types
* Recipe: Binary + operator supports implicit casts only for numbers and strings
## Recipe: `delete` operator is not supported ## Recipe: `delete` operator is not supported
**Rule `arkts-no-delete`** **Rule `arkts-no-delete`**
...@@ -1999,8 +1900,8 @@ delete p.y ...@@ -1999,8 +1900,8 @@ delete p.y
// and assign null to mark value absence: // and assign null to mark value absence:
class Point { class Point {
x: number | null x: number | null = 0
y: number | null y: number | null = 0
} }
let p = new Point() let p = new Point()
...@@ -2023,8 +1924,8 @@ p.y = null ...@@ -2023,8 +1924,8 @@ p.y = null
**Severity: error** **Severity: error**
ArkTS supports `typeof` operator only in the expression context. Specifying ArkTS supports `typeof` operator only in the expression context. Using
type notations using `typeof` is not supported. `typeof` to specify type notations is not supported.
**TypeScript** **TypeScript**
...@@ -2059,77 +1960,19 @@ let s2: string ...@@ -2059,77 +1960,19 @@ let s2: string
* Recipe: Dynamic property declaration is not supported * Recipe: Dynamic property declaration is not supported
* Recipe: Usage of standard library is restricted * Recipe: Usage of standard library is restricted
## Recipe: Binary operators `*`, `/`, `%`, `-`, `<<`, `>>`, `>>>`, `&`, `^` and `|` work only on numeric types ## Recipe: Binary `+` operator supports implicit casts only for numbers, enums and strings
**Rule `arkts-no-polymorphic-binops`**
**Severity: error**
ArkTS allows applying binary operators `*`, `/`, `%`, `-`, `<<`,
`>>`, `>>>`, `&`, `^` and `|` only to values of numeric types.
Implicit casts from other types to numeric types are prohibited and cause
compile-time errors.
**TypeScript**
```typescript
let a = (5 & 5) // 5
let b = (5.5 & 5.5) // 5, not 5.5
let c = (5 | 5) // 5
let d = (5.5 | 5.5) // 5, not 5.5
enum Direction {
Up = -1,
Down
}
let e = Direction.Up >> 1 // -1
let f = Direction.Up >>> 1 // 2147483647
let g = ("10" as any) << 1 // 20
let h = ("str" as any) << 1 // 0
let i = 10 * 5
let j = 10 / 5
let k = 10 % 5
let l = 10 - 5
```
**ArkTS**
```typescript
let a = (5 & 5) // 5
let b = (5.5 & 5.5) // Compile-time error
let c = (5 | 5) // 5
let d = (5.5 | 5.5) // Compile-time error
enum Direction {
Up,
Down
}
let e = Direction.Up >> 1 // 0
let f = Direction.Up >>> 1 // 0
let i = 10 * 5
let j = 10 / 5
let k = 10 % 5
let l = 10 - 5
```
**See also**
* Recipe: Unary operators +, - and ~ work only on numbers
* Recipe: Unary + cannot be used for casting to number
* Recipe: Binary + operator supports implicit casts only for numbers and strings
## Recipe: Binary `+` operator supports implicit casts only for numbers and strings
**Rule `arkts-no-polymorphic-plus`** **Rule `arkts-no-polymorphic-plus`**
**Severity: error** **Severity: error**
ArkTS supports implicit casts for `+` only for strings and numbers. If one of the operands of the binary `+` operator is of the string type
Elsewhere, any form of an explicit cast to string is required. (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**
...@@ -2145,6 +1988,10 @@ let e = "Hello, " + "world!" // "Hello, world!" ...@@ -2145,6 +1988,10 @@ let e = "Hello, " + "world!" // "Hello, world!"
let f = "string" + true // "stringtrue" let f = "string" + true // "stringtrue"
let g = (new Object()) + "string" // "[object Object]string" let g = (new Object()) + "string" // "[object Object]string"
let i = true + true // JS: 2, TS: compile-time error
let j = true + 2 // JS: 3, TS: compile-time error
let k = E.E1 + true // JS: 1, TS: compile-time error
``` ```
**ArkTS** **ArkTS**
...@@ -2161,13 +2008,16 @@ let e = "Hello, " + "world!" // "Hello, world!" ...@@ -2161,13 +2008,16 @@ let e = "Hello, " + "world!" // "Hello, world!"
let f = "string" + true // "stringtrue" let f = "string" + true // "stringtrue"
let g = (new Object()).toString() + "string" 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** **See also**
* Recipe: Unary operators +, - and ~ work only on numbers * Recipe: Unary operators +, - and ~ work only on numbers
* Recipe: Unary + cannot be used for casting to number
* Recipe: Binary operators \*, /, %, -, <<, >>, >>>, &, ^ and | work only on numeric types
## Recipe: `instanceof` operator is partially supported ## Recipe: `instanceof` operator is partially supported
...@@ -2175,40 +2025,38 @@ let g = (new Object()).toString() + "string" ...@@ -2175,40 +2025,38 @@ let g = (new Object()).toString() + "string"
**Severity: error** **Severity: error**
In TypeScript, the left-hand side of an `instanceof` expression must be of type In TypeScript, the left-hand side of an `instanceof` expression must be of the type
`any`, an object type or a type parameter, otherwise the result is `false`. `any`, an object type or a type parameter; the result is `false` otherwise.
In ArkTS, the left-hand side expression may be of any reference type, otherwise In ArkTS, the left-hand side expression may be of any reference type;
a compile-time error occurs. In addition, the left operand in ArkTS cannot be a compile-time error occurs otherwise. In addition, the left operand in ArkTS
a type. cannot be a type.
**TypeScript** **TypeScript**
```typescript ```typescript
class X {} class X {
// ...
}
let a = (new X()) instanceof Object // true let a = (new X()) instanceof Object // true
let b = (new X()) instanceof X // true let b = (new X()) instanceof X // true
// left operand is a type:
let c = X instanceof Object // true
let d = X instanceof X // false
// left operand is not of type any let c = X instanceof Object // true, left operand is a type
let e = (5.0 as Number) instanceof Number // false let d = X instanceof X // false, left operand is a type
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
class X {} class X {
// ...
}
let a = (new X()) instanceof Object // true let a = (new X()) instanceof Object // true
let b = (new X()) instanceof X // true let b = (new X()) instanceof X // true
// left operand is a type:
let c = X instanceof Object // Compile-time error
let d = X instanceof X // Compile-time error
// left operand may be of any reference type, like number let c = X instanceof Object // Compile-time error, left operand is a type
let e = (5.0 as Number) instanceof Number // true let d = X instanceof X // Compile-time error, left operand is a type
``` ```
## Recipe: `in` operator is not supported ## Recipe: `in` operator is not supported
...@@ -2217,9 +2065,9 @@ let e = (5.0 as Number) instanceof Number // true ...@@ -2217,9 +2065,9 @@ let e = (5.0 as Number) instanceof Number // true
**Severity: error** **Severity: error**
ArkTS does not support the `in` operator. However, this operator makes ArkTS does not support the operator `in`. However, this operator makes
little sense since the object layout is known at compile time and cannot little sense since the object layout is known at compile time, and cannot
be modified at runtime. Use `instanceof` as a work-around if you still need be modified at runtime. Use `instanceof` as a workaround if you still need
to check whether certain class members exist. to check whether certain class members exist.
**TypeScript** **TypeScript**
...@@ -2261,8 +2109,8 @@ let b = p instanceof Person // true, and "name" is guaranteed to be present ...@@ -2261,8 +2109,8 @@ let b = p instanceof Person // true, and "name" is guaranteed to be present
**Severity: error** **Severity: error**
ArkTS does not support destructuring assignment. Other idioms (e.g., ArkTS does not support destructuring assignment. Use other idioms (e.g.,
using a temporary variable, where applicable) can be used for replacement. a temporary variable, where applicable) for replacement.
**TypeScript** **TypeScript**
...@@ -2285,11 +2133,11 @@ let tmp = one ...@@ -2285,11 +2133,11 @@ let tmp = one
one = two one = two
two = tmp two = tmp
let data: Number[] = [1,2,3,4] let data: Number[] = [1, 2, 3, 4]
let head = data[0] let head = data[0]
let tail = new Number[data.length - 1] let tail: Number[] = []
for (let i = 1; i < data.length; ++i) { for (let i = 1; i < data.length; ++i) {
tail[i - 1] = data[i] tail.push(data[i])
} }
``` ```
...@@ -2378,9 +2226,9 @@ let y = zp.y ...@@ -2378,9 +2226,9 @@ let y = zp.y
**Severity: error** **Severity: error**
Currently, ArkTS does not support inference of implied types. Use explicit Currently, ArkTS does not support inference of implied types.
type notation instead. Use `Object[]` if you need containers that hold Use explicit type notation instead.
data of mixed types. Use `Object[]` if you need containers that hold data of mixed types.
**TypeScript** **TypeScript**
...@@ -2407,9 +2255,8 @@ let c1 = arr[2] ...@@ -2407,9 +2255,8 @@ let c1 = arr[2]
**Severity: error** **Severity: error**
In TypeScript catch clause variable type annotation must be `any` or `unknown` In TypeScript, catch clause variable type annotation must be `any` or `unknown`
if specified. As ArkTS does not support these types, a type annotation should if specified. As ArkTS does not support these types, omit type annotations.
be omitted.
**TypeScript** **TypeScript**
...@@ -2417,7 +2264,9 @@ be omitted. ...@@ -2417,7 +2264,9 @@ be omitted.
try { try {
// some code // some code
} }
catch (a: unknown) {} catch (a: unknown) {
// handle error
}
``` ```
**ArkTS** **ArkTS**
...@@ -2426,7 +2275,9 @@ catch (a: unknown) {} ...@@ -2426,7 +2275,9 @@ catch (a: unknown) {}
try { try {
// some code // some code
} }
catch (a) {} catch (a) {
// handle error
}
``` ```
**See also** **See also**
...@@ -2441,8 +2292,8 @@ catch (a) {} ...@@ -2441,8 +2292,8 @@ catch (a) {}
ArkTS does not support the iteration over object contents by the ArkTS does not support the iteration over object contents by the
`for .. in` loop. For objects, iteration over properties at runtime is `for .. in` loop. For objects, iteration over properties at runtime is
considered redundant because object layout is known at compile time and cannot considered redundant because object layout is known at compile time, and
change at runtime. For arrays, you can iterate with the regular `for` loop. cannot change at runtime. For arrays, iterate with the regular `for` loop.
**TypeScript** **TypeScript**
...@@ -2469,7 +2320,7 @@ for (let i = 0; i < a.length; ++i) { ...@@ -2469,7 +2320,7 @@ for (let i = 0; i < a.length; ++i) {
## Recipe: Iterable interfaces are not supported ## Recipe: Iterable interfaces are not supported
**Rule `arkts-noiterable`** **Rule `arkts-no-iterable`**
**Severity: error** **Severity: error**
...@@ -2505,7 +2356,7 @@ for (let s of a) { ...@@ -2505,7 +2356,7 @@ for (let s of a) {
```typescript ```typescript
let a: Set<number> = new Set([1, 2, 3]) let a: Set<number> = new Set([1, 2, 3])
let numbers = a.values() let numbers = Array.from(a.values())
for (let n of numbers) { for (let n of numbers) {
console.log(n) console.log(n)
} }
...@@ -2523,7 +2374,7 @@ for (let n of numbers) { ...@@ -2523,7 +2374,7 @@ for (let n of numbers) {
**Severity: error** **Severity: error**
ArkTS does not support mapped types. Use other language idioms and regular ArkTS does not support mapped types. Use other language idioms and regular
classes to achieve the same behaviour. classes to achieve that same behaviour.
**TypeScript** **TypeScript**
...@@ -2558,7 +2409,23 @@ class CFlags { ...@@ -2558,7 +2409,23 @@ class CFlags {
**Severity: error** **Severity: error**
ArkTS does not support the `with` statement. Use other language idioms ArkTS does not support the `with` statement. Use other language idioms
(including fully qualified names of functions) to achieve the same behaviour. (including fully qualified names of functions) to achieve that same behaviour.
**TypeScript**
```typescript
with (Math) { // Compile-time error, but JavaScript code still emitted
let r: number = 42
console.log("Area: ", PI * r * r)
}
```
**ArkTS**
```typescript
let r: number = 42
console.log("Area: ", Math.PI * r * r)
```
## Recipe: Values computed at runtime are not supported in `case` statements ## Recipe: Values computed at runtime are not supported in `case` statements
...@@ -2688,6 +2555,7 @@ explicitly. ...@@ -2688,6 +2555,7 @@ explicitly.
**TypeScript** **TypeScript**
```typescript ```typescript
// Compile-time error with noImplicitAny
function f(x: number) { function f(x: number) {
if (x <= 0) { if (x <= 0) {
return x return x
...@@ -2695,6 +2563,7 @@ function f(x: number) { ...@@ -2695,6 +2563,7 @@ function f(x: number) {
return g(x) return g(x)
} }
// Compile-time error with noImplicitAny
function g(x: number) { function g(x: number) {
return f(x - 1) return f(x - 1)
} }
...@@ -2718,8 +2587,8 @@ function f(x: number) : number { ...@@ -2718,8 +2587,8 @@ function f(x: number) : number {
return g(x) return g(x)
} }
// Explicit return type is required: // Return type may be omitted, it is inferred from f's explicit type:
function g(x: number) : number { function g(x: number) {
return f(x - 1) return f(x - 1)
} }
...@@ -2738,8 +2607,8 @@ console.log(doOperation(2, 3)) ...@@ -2738,8 +2607,8 @@ console.log(doOperation(2, 3))
**Severity: error** **Severity: error**
ArkTS requires that parameters must be passed directly to the function, and ArkTS requires parameters to be passed directly to the function, and
local names must be assigned manually. local names to be assigned manually.
**TypeScript** **TypeScript**
...@@ -2824,7 +2693,7 @@ ArkTS does not support the usage of `this` inside stand-alone functions. ...@@ -2824,7 +2693,7 @@ ArkTS does not support the usage of `this` inside stand-alone functions.
```typescript ```typescript
function foo(i: number) { function foo(i: number) {
this.count = i this.count = i // Compile-time error only with noImplicitThis
} }
class A { class A {
...@@ -2983,7 +2852,7 @@ function main(): void { ...@@ -2983,7 +2852,7 @@ function main(): void {
**Severity: error** **Severity: error**
ArkTS has no keyof operator because the object layout is defined ArkTS has no keyof operator because the object layout is defined
at compile time and cannot be changed at runtime. Object fields can only be at compile time, and cannot be changed at runtime. Object fields can only be
accessed directly. accessed directly.
**TypeScript** **TypeScript**
...@@ -3021,7 +2890,6 @@ function getPropertyValue(obj: Point, key: string): number { ...@@ -3021,7 +2890,6 @@ function getPropertyValue(obj: Point, key: string): number {
return obj.y return obj.y
} }
throw new Error() // No such property throw new Error() // No such property
return 0
} }
function main(): void { function main(): void {
...@@ -3038,7 +2906,7 @@ function main(): void { ...@@ -3038,7 +2906,7 @@ function main(): void {
**Severity: error** **Severity: error**
The only supported scenario for the spread operator is to spread an array into The only supported scenario for the spread operator is to spread an array into
the rest parameter. Otherwise manually “unpack” data from arrays and objects, the rest parameter. Otherwise, manually “unpack” data from arrays and objects,
where necessary. where necessary.
**TypeScript** **TypeScript**
...@@ -3097,15 +2965,15 @@ console.log(p3d.x, p3d.y, p3d.z) ...@@ -3097,15 +2965,15 @@ console.log(p3d.x, p3d.y, p3d.z)
## Recipe: Interface declarations (extends same property) ## Recipe: Interface declarations (extends same property)
**Rule `arkts-no-extend-same-property`** **Rule `arkts-no-extend-same-prop`**
**Severity: error** **Severity: error**
In TypeScript, an interface that extends two other interfaces with the same method, In TypeScript, an interface that extends two other interfaces with the same method
must declare that method with a combined result type. It is not allowed in must declare that method with a combined result type. It is not allowed in
ArkTS because ArkTS does not allow an interface to contain two methods with ArkTS because ArkTS does not allow an interface to contain two methods with
signatures that are not distinguishable, e.g., two methods that have the same signatures that are not distinguishable, e.g., two methods that have the same
parameter lists, but different return types. parameter lists but different return types.
**TypeScript** **TypeScript**
...@@ -3198,8 +3066,8 @@ class C implements Mover, Shaker { ...@@ -3198,8 +3066,8 @@ class C implements Mover, Shaker {
**Severity: error** **Severity: error**
ArkTS does not support merging declratations. All definitions of classes, ArkTS does not support merging declratations. Keep all definitions of classes,
interfaces and so on must be kept compact in the code base. interfaces and so on compact in the codebase.
**TypeScript** **TypeScript**
...@@ -3270,11 +3138,13 @@ interface SelectableControl extends Control { ...@@ -3270,11 +3138,13 @@ interface SelectableControl extends Control {
**Severity: error** **Severity: error**
ArkTS requires that object layout is determined in compile-time and cannot ArkTS requires that object layout is determined at compile time, and cannot
be changed at runtime. There for no runtime property-based checks are supported. be changed at runtime. Therefore, property-based runtime checks are not
If you need to do a type cast, use `as` operator and use desired properties supported.
and methods. If some property doesn’t exist then an attempt to reference it If you need to do a type cast, use the operator `as` with desired properties
will result in a compile-time error. and methods.
If some property does not exist, then an attempt to refer to it causes a
compile-time error.
**TypeScript** **TypeScript**
...@@ -3385,10 +3255,10 @@ const person = createPerson(Impersonizer, "John", 30) ...@@ -3385,10 +3255,10 @@ const person = createPerson(Impersonizer, "John", 30)
**Severity: error** **Severity: error**
ArkTS does not support dynamic property declaration. All object properties must ArkTS does not support dynamic property declaration. Declare all object
be declared immediately in the class. While it can be replaced with an array properties immediately in the class. While replacement for an array of
of objects, it is still better to adhere to the static language paradigm and objects is possible, it is still better to adhere to the static language
declare fields, their names and types explicitly. paradigm, and declare fields, their names and types explicitly.
**TypeScript** **TypeScript**
...@@ -3403,7 +3273,7 @@ const person: Person = { ...@@ -3403,7 +3273,7 @@ const person: Person = {
name: "John", name: "John",
age: 30, age: 30,
email: "john@example.com", email: "john@example.com",
phone: 1234567890, phoneNumber: 1234567890,
} }
``` ```
...@@ -3414,13 +3284,13 @@ class Person { ...@@ -3414,13 +3284,13 @@ class Person {
name: string name: string
age: number age: number
email: string email: string
phone: number phoneNumber: number
constructor(name: string, age: number, email: string, phone: number) { constructor(name: string, age: number, email: string, phoneNumber: number) {
this.name = name this.name = name
this.age = age this.age = age
this.email = email this.email = email
this.phone = phone this.phoneNumber = phoneNumber
} }
} }
...@@ -3448,7 +3318,7 @@ function main(): void { ...@@ -3448,7 +3318,7 @@ function main(): void {
ArkTS does not support initializing members of enumerations with expressions ArkTS does not support initializing members of enumerations with expressions
that are evaluated during program runtime. Besides, all explicitly set that are evaluated during program runtime. Besides, all explicitly set
initializers must be of the same time. initializers must be of the same type.
**TypeScript** **TypeScript**
...@@ -3494,8 +3364,8 @@ enum E2 { ...@@ -3494,8 +3364,8 @@ enum E2 {
**Severity: error** **Severity: error**
ArkTS does not support merging declratations for `enum`. ArkTS does not support merging declratations for `enum`. Keep the
The declaration of each `enum` must be kept compact in the code base. declaration of each `enum` compact in the codebase.
**TypeScript** **TypeScript**
...@@ -3555,26 +3425,6 @@ namespace MyNamespace { ...@@ -3555,26 +3425,6 @@ namespace MyNamespace {
MyNamespace.x = 2 MyNamespace.x = 2
``` ```
## Recipe: Scripts and modules
**Rule `arkts-no-scripts`**
**Severity: error**
In general, scripts and modules in ArkTS are very close to TypeScript.
Differences are described in separate recipes.
**See also**
* Recipe: Special import type declarations are not supported
* Recipe: Importing a module for side-effects only is not supported
* Recipe: import default as ... is not supported
* Recipe: require is not supported
* Recipe: Renaming in export declarations is not supported
* Recipe: Export list declaration is not supported
* Recipe: Re-exporting is not supported
* Recipe: export = ... assignment is not supported
## Recipe: Non-declaration statements in namespaces are not supported ## Recipe: Non-declaration statements in namespaces are not supported
**Rule `arkts-no-ns-statements`** **Rule `arkts-no-ns-statements`**
...@@ -3621,23 +3471,23 @@ Use ordinary import instead. ...@@ -3621,23 +3471,23 @@ Use ordinary import instead.
```typescript ```typescript
// Re-using the same import // Re-using the same import
import { APIResponseType } from "./api" import { APIResponseType } from "api"
// Explicitly use import type // Explicitly use import type
import type { APIResponseType } from "./api" import type { APIResponseType } from "api"
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
import { APIResponseType } from "./api" import { APIResponseType } from "api"
``` ```
**See also** **See also**
* Recipe: Importing a module for side-effects only is not supported * Recipe: Importing a module for side-effects only is not supported
* Recipe: import default as ... is not supported * Recipe: import default as ... is not supported
* Recipe: require is not supported * Recipe: require and import assignment are not supported
## Recipe: Importing a module for side-effects only is not supported ## Recipe: Importing a module for side-effects only is not supported
...@@ -3689,13 +3539,15 @@ import { default as d } from "mod" ...@@ -3689,13 +3539,15 @@ import { default as d } from "mod"
import d from "mod" import d from "mod"
``` ```
## Recipe: `require` is not supported ## Recipe: `require` and `import` assignment are not supported
**Rule `arkts-no-require`** **Rule `arkts-no-require`**
**Severity: error** **Severity: error**
ArkTS does not support importing via `require`. Use `import` instead. ArkTS does not support importing via `require`.
`import` assignments are not supported either.
Use regular `import` instead.
**TypeScript** **TypeScript**
...@@ -3709,139 +3561,59 @@ import m = require("mod") ...@@ -3709,139 +3561,59 @@ import m = require("mod")
import * as m from "mod" import * as m from "mod"
``` ```
## Recipe: Renaming in export declarations is not supported
**Rule `arkts-no-export-renaming`**
**Severity: error**
ArkTS does not support renaming in export declarations. Similar effect
can be achieved through setting an alias for the exported entity.
**TypeScript**
```typescript
// file1.ts
class MyClass {
// ...
}
export { MyClass as RenamedClass }
// file2.ts
import { RenamedClass } from "./file1"
function main(): void {
const myObject = new RenamedClass()
// ...
}
```
**ArkTS**
```typescript
// module1
class MyClass {
// ...
}
export type RenamedClass = MyClass
// module2
import { RenamedClass } from "./module1"
function main(): void {
const myObject = new RenamedClass()
// ...
}
```
**See also**
* Recipe: Export list declaration is not supported
* Recipe: Re-exporting is not supported
* Recipe: export = ... assignment is not supported
## Recipe: Export list declaration is not supported
**Rule `arkts-no-export-list-decl`**
**Severity: error**
ArkTS does not support syntax of export list declarations. All exported
entities must be explicitly annotated with the `export` keyword.
**TypeScript**
```typescript
export { x }
export { x } from "mod"
export { x, y as b, z as c }
```
**ArkTS**
```typescript
let x = 1
class MyClass {}
export let y = x, z: number = 2
export RenamedClass = MyClass
```
**See also** **See also**
* Recipe: Renaming in export declarations is not supported
* Recipe: Re-exporting is not supported
* Recipe: export = ... assignment is not supported * Recipe: export = ... assignment is not supported
## Recipe: Re-exporting is not supported ## Recipe: Re-exporting is supported with restrictions
**Rule `arkts-no-reexport`** **Rule `arkts-limited-reexport`**
**Severity: error** **Severity: error**
ArkTS does not support re-exporting. All desired entities must be ArkTS supports re-exporting syntax which covers most common cases of re-export:
imported explicitly from the modules that export them. re-exporting imported entities and re-exporting which is combined with renaming.
Other syntax flavors like `export * as ...` are not supported.
**TypeScript** **TypeScript**
```typescript ```typescript
// module1 // module1
export class MyClass { export class Class1 {
// ...
}
export class Class2 {
// ... // ...
} }
// module2 // module2
export { MyClass } from "module1" export * as utilities from "module1"
// consumer module // consumer module
import { MyClass } from "module2" import { utilities } from "module2"
const myInstance = new MyClass()
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
// module1 // module1
export class MyClass { export class Class1 {
// ...
}
export class C2 {
// ... // ...
} }
// module2 // module2
// some stuff export { Class1 } from "module1"
export { C2 as Class2 } from "module1"
// consumer module // consumer module
import { MyClass } from "module1" import { Class1, Class2 } from "module2"
import * from "module2"
const myInstance = new MyClass()
``` ```
**See also** **See also**
* Recipe: Renaming in export declarations is not supported
* Recipe: Export list declaration is not supported
* Recipe: export = ... assignment is not supported * Recipe: export = ... assignment is not supported
## Recipe: `export = ...` assignment is not supported ## Recipe: `export = ...` assignment is not supported
...@@ -3887,30 +3659,47 @@ let p = Pt.origin ...@@ -3887,30 +3659,47 @@ let p = Pt.origin
**See also** **See also**
* Recipe: Renaming in export declarations is not supported * Recipe: require and import assignment are not supported
* Recipe: Export list declaration is not supported * Recipe: Re-exporting is supported with restrictions
* Recipe: Re-exporting is not supported
## Recipe: Special export type declarations are not supported ## Recipe: Special `export type` declarations are not supported
**Rule `arkts-no-special-exports`** **Rule `arkts-no-special-exports`**
**Severity: error** **Severity: error**
ArkTS does not have a special notation for exporting types. ArkTS does not have a special notation for exporting types through
Use ordinary export instead. `export type ...`. Use ordinary export instead.
**TypeScript** **TypeScript**
```typescript ```typescript
class C {} // Explicitly exported class:
export type { C } export class Class1 {
// ...
}
// Declared class later exported through export type ...
class Class2 {
// ...
}
// This is not supported:
export type { Class2 }
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
export class C {} // Explicitly exported class:
export class Class1 {
// ...
}
// Explicitly exported class:
export class Class2 {
// ...
}
``` ```
## Recipe: Ambient module declaration is not supported ## Recipe: Ambient module declaration is not supported
...@@ -3934,7 +3723,7 @@ declare module "someModule" { ...@@ -3934,7 +3723,7 @@ declare module "someModule" {
```typescript ```typescript
// Import what you need from the original module // Import what you need from the original module
import { normalize } from "../someModule" import { normalize } from "someModule"
``` ```
**See also** **See also**
...@@ -3948,16 +3737,34 @@ import { normalize } from "../someModule" ...@@ -3948,16 +3737,34 @@ import { normalize } from "../someModule"
**Severity: error** **Severity: error**
ArkTS does not supported wildcards in module names because in ArkTS, import ArkTS does not support wildcards in module names because in the language
is a compile-time, not a runtime feature. Use ordinary export syntax instead. import is a compile-time, not a runtime feature.
Use ordinary export syntax instead.
**TypeScript** **TypeScript**
```typescript ```typescript
// Declaration:
declare module "*!text" { declare module "*!text" {
const content: string const content: string
export default content export default content
} }
// Consuming code:
import fileContent from "some.txt!text"
```
**ArkTS**
```typescript
// Declaration:
declare namespace N {
function foo(x: number): number
}
// Consuming code:
import * from "module"
console.log("N.foo called: ", N.foo(42))
``` ```
**See also** **See also**
...@@ -3972,10 +3779,10 @@ declare module "*!text" { ...@@ -3972,10 +3779,10 @@ declare module "*!text" {
**Severity: error** **Severity: error**
ArkTS does not support universal module definitions (UMD) because in ArkTS ArkTS does not support universal module definitions (UMD) because in the
there is no concept of “script” (as opposed to “module”). Besides, in ArkTS language there is no concept of “script” (as opposed to “module”).
import is a compile-time, not a runtime feature. Use ordinary syntax for Besides, in ArkTS import is a compile-time, not a runtime feature.
`export` and `import` instead. Use ordinary syntax for `export` and `import` instead.
**TypeScript** **TypeScript**
...@@ -3997,7 +3804,7 @@ namespace mathLib { ...@@ -3997,7 +3804,7 @@ namespace mathLib {
} }
// in program // in program
import { mathLib } from "./math-lib" import { mathLib } from "math-lib"
mathLib.isPrime(2) mathLib.isPrime(2)
``` ```
...@@ -4011,19 +3818,19 @@ mathLib.isPrime(2) ...@@ -4011,19 +3818,19 @@ mathLib.isPrime(2)
**Severity: error** **Severity: error**
ArkTS does not allow to use `.js` extension in module identifiers because it ArkTS does not allow using `.js` extension in module identifiers because
has its own mechanisms for interoperating with JavaScript. it has its own mechanisms for interoperating with JavaScript.
**TypeScript** **TypeScript**
```typescript ```typescript
import { something } from "./module.js" import { something } from "module.js"
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
import { something } from "./module" import { something } from "module"
``` ```
**See also** **See also**
...@@ -4039,7 +3846,7 @@ import { something } from "./module" ...@@ -4039,7 +3846,7 @@ import { something } from "./module"
ArkTS does not support `new.target` because there is no concept of runtime ArkTS does not support `new.target` because there is no concept of runtime
prototype inheritance in the language. This feature is considered not applicable prototype inheritance in the language. This feature is considered not applicable
to the statically typing. to static typing.
**TypeScript** **TypeScript**
...@@ -4055,6 +3862,20 @@ class CustomError extends Error { ...@@ -4055,6 +3862,20 @@ class CustomError extends Error {
} }
``` ```
**ArkTS**
```typescript
class CustomError extends Error {
constructor(message?: string) {
// Call parent's constructor, inheritance chain is static and
// cannot be modified in runtime
super(message)
console.log(this instanceof Error) // true
}
}
let ce = new CustomError()
```
**See also** **See also**
* Recipe: Prototype assignment is not supported * Recipe: Prototype assignment is not supported
...@@ -4066,19 +3887,19 @@ class CustomError extends Error { ...@@ -4066,19 +3887,19 @@ class CustomError extends Error {
**Severity: error** **Severity: error**
ArkTS does not support such “runtime” import expressions as `await import...` ArkTS does not support such “runtime” import expressions as `await import...`
because in ArkTS import is a compile-time, not a runtime feature. Use regular because in the language import is a compile-time, not a runtime feature.
import syntax instead. Use regular import syntax instead.
**TypeScript** **TypeScript**
```typescript ```typescript
const zipUtil = await import("./utils/create-zip-file") const zipUtil = await import("utils/create-zip-file")
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
import { zipUtil } from "./utils/create-zip-file" import { zipUtil } from "utils/create-zip-file"
``` ```
**See also** **See also**
...@@ -4094,8 +3915,8 @@ import { zipUtil } from "./utils/create-zip-file" ...@@ -4094,8 +3915,8 @@ import { zipUtil } from "./utils/create-zip-file"
**Severity: error** **Severity: error**
ArkTS does not support definite assignment assertions `let v!: T` because ArkTS does not support definite assignment assertions `let v!: T` because
they are considered an excessive compiler hint. Use declaration with they are considered an excessive compiler hint.
initialization instead. Use declaration with initialization instead.
**TypeScript** **TypeScript**
...@@ -4129,17 +3950,18 @@ console.log("x = " + x) ...@@ -4129,17 +3950,18 @@ console.log("x = " + x)
**Severity: error** **Severity: error**
ArkTS does not support IIFEs as namespace declarations because in ArkTS, ArkTS does not support IIFEs as namespace declarations because anonymous
anonymous functions cannot serve as namespaces. Use regular syntax for functions in the language cannot serve as namespaces.
namespaces instead. Use regular syntax for namespaces instead.
**TypeScript** **TypeScript**
```typescript ```typescript
var C = (function() { var C = (function() {
function C(n) { function C(n: number) {
this.p = n this.p = n // Compile-time error only with noImplicitThis
} }
C.staticProperty = 0
return C return C
})() })()
C.staticProperty = 1 C.staticProperty = 1
...@@ -4161,13 +3983,14 @@ namespace C { ...@@ -4161,13 +3983,14 @@ namespace C {
ArkTS does not support prototype assignment because there is no concept of ArkTS does not support prototype assignment because there is no concept of
runtime prototype inheritance in the language. This feature is considered not runtime prototype inheritance in the language. This feature is considered not
applicable to the static typing. applicable to static typing. Mechanism of classes and / or interfaces must
be used instead to statically “combine” methods to data together.
**TypeScript** **TypeScript**
```typescript ```typescript
var C = function(p) { var C = function(p: number) {
this.p = p this.p = p // Compile-time error only with noImplicitThis
} }
C.prototype = { C.prototype = {
...@@ -4176,8 +3999,22 @@ C.prototype = { ...@@ -4176,8 +3999,22 @@ C.prototype = {
} }
} }
C.prototype.q = function(r) { C.prototype.q = function(r: number) {
return this.p === r return this.p == r
}
```
**ArkTS**
```typescript
class C {
p: number = 0
m() {
console.log(this.p)
}
q(r: number) {
return this.p == r
}
} }
``` ```
...@@ -4211,7 +4048,7 @@ globalThis.abc = 200 ...@@ -4211,7 +4048,7 @@ globalThis.abc = 200
export let abc : number = 0 export let abc : number = 0
// file2 // file2
import * as M from "../file1" import * as M from "file1"
M.abc = 200 M.abc = 200
``` ```
...@@ -4221,15 +4058,18 @@ M.abc = 200 ...@@ -4221,15 +4058,18 @@ M.abc = 200
* Recipe: Declaring properties on functions is not supported * Recipe: Declaring properties on functions is not supported
* Recipe: Usage of standard library is restricted * Recipe: Usage of standard library is restricted
## Recipe: Utility types are not supported ## Recipe: Some of utility types are not supported
**Rule `arkts-no-utility-types`** **Rule `arkts-no-utility-types`**
**Severity: error** **Severity: error**
Currently ArkTS does not support utility types from TypeScript extensions to the Currently ArkTS does not support utility types from TypeScript extensions to the
standard library (`Omit`, `Partial`, `Readonly`, `Record`, `Pick`, standard library (`Omit`, `Pick`, etc.). Exceptions are: `Partial`,
etc.). `Record`.
For the type *Record<K, V>*, the type of an indexing expression *rec[index]* is
of the type *V | undefined*.
**TypeScript** **TypeScript**
...@@ -4241,20 +4081,55 @@ type Person = { ...@@ -4241,20 +4081,55 @@ type Person = {
} }
type QuantumPerson = Omit<Person, "location"> type QuantumPerson = Omit<Person, "location">
let persons : Record<string, Person> = {
"Alice": {
name: "Alice",
age: 32,
location: "Shanghai"
},
"Bob": {
name: "Bob",
age: 48,
location: "New York"
}
}
console.log(persons["Bob"].age)
console.log(persons["Rob"].age) // Runtime exception
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
class Person { class Person {
name: string name: string = ""
age: number age: number = 0
location: string location: string = ""
} }
class QuantumPerson { class QuantumPerson {
name: string name: string = ""
age: number age: number = 0
}
type OptionalPerson = Person | undefined
let persons : Record<string, OptionalPerson> = {
// Or:
// let persons : Record<string, Person | undefined> = {
"Alice": {
name: "Alice",
age: 32,
location: "Shanghai"
},
"Bob": {
name: "Bob",
age: 48,
location: "New York"
}
}
console.log(persons["Bob"]!.age)
if (persons["Rob"]) { // Explicit value check, no runtime exception
console.log(persons["Rob"].age)
} }
``` ```
...@@ -4303,15 +4178,17 @@ class MyImage { ...@@ -4303,15 +4178,17 @@ class MyImage {
// ... // ...
} }
function readImage( async function readImage(
path: string, callback: (err: Error, image: MyImage) => void path: string, callback: (err: Error, image: MyImage) => void
) : Promise<MyImage> ) : Promise<MyImage>
{ {
// async implementation // In real world, the implementation is more complex,
// involving real network / DB logic, etc.
return await new MyImage()
} }
function readImageSync(path: string) : MyImage { function readImageSync(path: string) : MyImage {
// sync implementation return new MyImage()
} }
``` ```
...@@ -4325,12 +4202,12 @@ function readImageSync(path: string) : MyImage { ...@@ -4325,12 +4202,12 @@ function readImageSync(path: string) : MyImage {
**Severity: error** **Severity: error**
ArkTS does not allow to use standard library functions `Function.apply`, ArkTS does not allow using standard library functions `Function.apply`,
`Function.bind`, `Function.call`. These APIs are needed in the standard `Function.bind` and `Function.call`. These APIs are needed in the standard
library to explicitly set `this` parameter for the called function. library to explicitly set `this` parameter for the called function.
In ArkTS semantics of `this` is restricted to the conventional OOP style, In ArkTS the semantics of `this` is restricted to the conventional OOP
and usage of `this` in stand-alone functions is prohibited. Thus these style, and the usage of `this` in stand-alone functions is prohibited.
functions are excessive. Thus these functions are excessive.
**TypeScript** **TypeScript**
...@@ -4382,7 +4259,7 @@ console.log(person1.fullName()) ...@@ -4382,7 +4259,7 @@ console.log(person1.fullName())
**Severity: error** **Severity: error**
Currently ArkTS supports `readonly` for properties, but not for parameters. Currently, ArkTS supports `readonly` for properties, but not for parameters.
**TypeScript** **TypeScript**
...@@ -4435,7 +4312,7 @@ let x : string = "hello" ...@@ -4435,7 +4312,7 @@ let x : string = "hello"
let y : number[] = [10, 20] let y : number[] = [10, 20]
class Label { class Label {
text : string text : string = ""
} }
// Type 'Label': // Type 'Label':
...@@ -4450,7 +4327,7 @@ let z : Label = { ...@@ -4450,7 +4327,7 @@ let z : Label = {
**Severity: error** **Severity: error**
ArkTS does not support import assertions because in ArkTS, import is a ArkTS does not support import assertions because in the language import is a
compile-time, not a runtime feature. So asserting correctness of imported APIs compile-time, not a runtime feature. So asserting correctness of imported APIs
in runtime does not make sense for the statically typed language. Use ordinary in runtime does not make sense for the statically typed language. Use ordinary
`import` syntax instead. `import` syntax instead.
...@@ -4458,14 +4335,14 @@ in runtime does not make sense for the statically typed language. Use ordinary ...@@ -4458,14 +4335,14 @@ in runtime does not make sense for the statically typed language. Use ordinary
**TypeScript** **TypeScript**
```typescript ```typescript
import { obj } from "./something.json" assert { type: "json" } import { obj } from "something.json" assert { type: "json" }
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
// Correctness of importing T will be checked in compile-time: // Correctness of importing T will be checked in compile-time:
import { something } from "./module" import { something } from "module"
``` ```
**See also** **See also**
...@@ -4480,10 +4357,10 @@ import { something } from "./module" ...@@ -4480,10 +4357,10 @@ import { something } from "./module"
**Severity: error** **Severity: error**
ArkTS does not allow usage of some APIs from the TypeScript/JavaScript standard library. ArkTS does not allow using some APIs from the TypeScript/JavaScript standard library.
The most part of the restricted APIs relates to manipulating objects in The most part of the restricted APIs relates to manipulating objects in a
dynamic manner, which is not compatible with the static typing. Following APIs dynamic manner, which is not compatible with static typing. The usage of
are prohibited from usage: the following APIs is prohibited:
Properties and functions of the global object: `eval`, Properties and functions of the global object: `eval`,
`Infinity`, `NaN`, `isFinite`, `isNaN`, `parseFloat`, `parseInt`, `Infinity`, `NaN`, `isFinite`, `isNaN`, `parseFloat`, `parseInt`,
...@@ -4526,3 +4403,161 @@ Properties and functions of the global object: `eval`, ...@@ -4526,3 +4403,161 @@ Properties and functions of the global object: `eval`,
* Recipe: Dynamic property declaration is not supported * Recipe: Dynamic property declaration is not supported
* Recipe: globalThis is not supported * Recipe: globalThis is not supported
## Recipe: Strict type checking is enforced
**Rule `arkts-strict-typing`**
**Severity: error**
Type checker in ArkTS is not optional, the code must be explicitly and
correctly types to be compiled and run. When porting from the standard TypeScript,
turn on the following flags: `noImplicitReturns`, `strictFunctionTypes`,
`strictNullChecks`, `strictPropertyInitialization`.
**TypeScript**
```typescript
class C {
n: number // Compile-time error only with strictPropertyInitialization
s: string // Compile-time error only with strictPropertyInitialization
}
// Compile-time error only with noImplicitReturns
function foo(s: string): string {
if (s != "") {
console.log(s)
return s
} else {
console.log(s)
}
}
let n: number = null // Compile-time error only with strictNullChecks
```
**ArkTS**
```typescript
class C {
n: number = 0
s: string = ""
}
function foo(s: string): string {
console.log(s)
return s
}
let n1: number | null = null
let n2: number = 0
```
**See also**
* Recipe: Use explicit types instead of any, unknown
* Recipe: Switching off type checks with in-place comments is not allowed
## Recipe: Switching off type checks with in-place comments is not allowed
**Rule `arkts-strict-typing-required`**
**Severity: error**
Type checker in ArkTS is not optional, the code must be explicitly and
correctly typed to be compiled and run. “Suppressing” type checker in-place
with special comments is not allowed. In particular, `@ts-ignore` and
`@ts-nocheck` annotations are not supported.
**TypeScript**
```typescript
// @ts-nocheck
// ...
// Some code with switched off type checker
// ...
let s1: string = null // No error, type checker suppressed
// @ts-ignore
let s2: string = null // No error, type checker suppressed
```
**ArkTS**
```typescript
let s1: string | null = null // No error, properly types
let s2: string = null // Compile-time error
```
**See also**
* Recipe: Use explicit types instead of any, unknown
* Recipe: Strict type checking is enforced
## Recipe: No dependencies on TypeScript code are currently allowed
**Rule `arkts-no-ts-deps`**
**Severity: error**
Currently, the codebase implemented in the standard TypeScript language must not
depend on ArkTS through importing the ArkTS codebase. Imports in reverse
direction are supported.
**TypeScript**
```typescript
// app.ets
export class C {
// ...
}
// lib.ts
import { C } from "app"
```
**ArkTS**
```typescript
// lib1.ets
export class C {
// ...
}
// lib2.ets
import { C } from "lib1"
```
## Recipe: No decorators except ArkUI decorators are currently allowed
**Rule `arkts-no-decorators-except-arkui`**
**Severity: error**
Currently, only ArkUI decorators are allowed in the ArkTS.
Any other decorator will cause a compile-time error.
**TypeScript**
```typescript
function classDecorator(x: any, y: any): void {
//
}
@classDecorator
class BugReport {
}
```
**ArkTS**
```typescript
function classDecorator(x: any, y: any): void {
//
}
@classDecorator // compile-time error: unsupported decorator
class BugReport {
}
```
...@@ -766,7 +766,7 @@ class Point { ...@@ -766,7 +766,7 @@ class Point {
x: number = 0 x: number = 0
y: number = 0 y: number = 0
} }
let p: Point = {42 ,42} let p: Point = {x: 42, y: 42}
``` ```
### 字段 ### 字段
...@@ -868,11 +868,11 @@ class Rectangle { ...@@ -868,11 +868,11 @@ class Rectangle {
} }
``` ```
实例方法需要在类的实例上调用 必须通过类的实例调用实例方法
```typescript ```typescript
let r = new Rectangle(10, 10) let square = new Rectangle(10, 10)
console.log(square.calculateArea()) // output: 100 console.log(square.calculateArea()) // 输出:100
``` ```
#### 静态方法 #### 静态方法
...@@ -883,7 +883,7 @@ console.log(square.calculateArea()) // output: 100 ...@@ -883,7 +883,7 @@ console.log(square.calculateArea()) // output: 100
所有实例都可以访问静态方法。 所有实例都可以访问静态方法。
要调用静态方法,需要使用类名 必须通过类名调用静态方法
```typescript ```typescript
class Cl { class Cl {
...@@ -1309,7 +1309,7 @@ class Stack<Element> { ...@@ -1309,7 +1309,7 @@ class Stack<Element> {
public pop(): Element { public pop(): Element {
// ... // ...
} }
public push(e: Element) { public push(e: Element):void {
// ... // ...
} }
} }
...@@ -1402,7 +1402,7 @@ foo<number>() ...@@ -1402,7 +1402,7 @@ foo<number>()
## 空安全 ## 空安全
默认情况下,ArkTS中的所有类型都是不可为空的,因此类型的值不能为空。这类似于TypeScript的严格空值检查模式(`strictNullChecks`),但规则更严格,而且ArkTS中没有`undefined`类型 默认情况下,ArkTS中的所有类型都是不可为空的,因此类型的值不能为空。这类似于TypeScript的严格空值检查模式(`strictNullChecks`),但规则更严格。
在下面的示例中,所有行都会导致编译时错误: 在下面的示例中,所有行都会导致编译时错误:
...@@ -1454,28 +1454,47 @@ class Person { ...@@ -1454,28 +1454,47 @@ class Person {
### 可选链 ### 可选链
可选链运算符`?.` 可以在编写代码时遇到求值为null的表达式就停止运行 在访问对象属性时,如果该属性是`undefined`或者`null`,可选链运算符会返回`undefined`
```typescript ```typescript
class Person { class Person {
// ... nick : string | null = null
spouse: Person | null = null spouse ?: Person
nick: string | null = null
getSpouseNick(): string | null { setSpouse(spouse: Person) : void {
this.spouse = spouse
}
getSpouseNick(): string | null | undefined {
return this.spouse?.nick return this.spouse?.nick
} }
constructor(nick: string) {
this.nick = nick
this.spouse = undefined
}
} }
``` ```
**说明**`getSpouseNick`的返回类型必须为`string | null`,因为该方法可能返回null **说明**`getSpouseNick`的返回类型必须为`string | null | undefined`,因为该方法可能返回`null`或者`undefined`
可选链可以是任何长度的,可包含任意数量的 `?.` 运算符。 可选链可以任意长,可以包含任意数量的`?.`运算符。
在以下示例中,如果某人有配偶,且配偶有昵称,则输出是该人的配偶昵称。否则,输出为空 在以下示例中,如果一个`Person`的实例有不为空的`spouse`属性,且`spouse`有不为空的`nickname`属性,则输出`spouse.nick`。否则,输出`undefined`
```typescript ```typescript
let p: Person = ... class Person {
console.log(p?.spouse?.nick) nick : string | null = null
spouse ?: Person
constructor(nick: string) {
this.nick = nick
this.spouse = undefined
}
}
let p: Person = new Person("Alice")
console.log(p.spouse?.nick) // 打印undefined
``` ```
## 模块 ## 模块
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
本文通过提供简洁的约束指导如何将标准的TypeScript代码重构为ArkTS代码。尽管ArkTS是基于TypeScript设计的,但出于性能考虑,一些TypeScript的特性被限制了。因此,在ArkTS中,所有的TypeScript特性被分成三类。 本文通过提供简洁的约束指导如何将标准的TypeScript代码重构为ArkTS代码。尽管ArkTS是基于TypeScript设计的,但出于性能考虑,一些TypeScript的特性被限制了。因此,在ArkTS中,所有的TypeScript特性被分成三类。
1. **完全支持的特性**:原始代码无需任何修改。根据测试,对于已遵循最佳TypeScript实践的项目,代码库中90%到97%的内容可以保持原封不动。 1. **完全支持的特性**:原始代码无需任何修改。根据测试,对于已遵循最佳TypeScript实践的项目,代码库中90%到97%的内容可以保持原封不动。
2. **部分支持的特性**:需小规模的代码重构。例如,必须使用关键字`let`代替`var` 来声明变量。注意,根据本文提供的约束进行代码重构后,您的代码仍为有效的TypeScript代码。 2. **部分支持的特性**:需小规模的代码重构。例如,必须使用关键字`let`代替`var`来声明变量。注意,根据本文提供的约束进行代码重构后,您的代码仍为有效的TypeScript代码。
3. **不支持的特性**:需大规模的代码重构。例如,不支持`any`类型,所有使用`any`的代码都需要引入显式类型。 3. **不支持的特性**:需大规模的代码重构。例如,不支持`any`类型,所有使用`any`的代码都需要引入显式类型。
本文将逐一介绍所有部分支持和所有不支持的特性,并提供代码重构的建议。对于没有提到的特性,则说明ArkTS完全支持。 本文将逐一介绍所有部分支持和所有不支持的特性,并提供代码重构的建议。对于没有提到的特性,则说明ArkTS完全支持。
...@@ -80,7 +80,7 @@ if (!res.succeeded()) { ...@@ -80,7 +80,7 @@ if (!res.succeeded()) {
} }
``` ```
`any`类型在TypeScript中并不常见,只有大约1%的TypeScript代码库使用。一些代码检查工具(例如ESLint)也制定一系列规则来禁止使用`any`。因此,虽然禁止`any` 将导致代码重构,但重构量很小,有助于整体性能提升,因此这个约束是非常有价值的。 `any`类型在TypeScript中并不常见,只有大约1%的TypeScript代码库使用。一些代码检查工具(例如ESLint)也制定一系列规则来禁止使用`any`。因此,虽然禁止`any`将导致代码重构,但重构量很小,有助于整体性能提升,因此这个约束是非常有价值的。
### 禁止在运行时变更对象布局 ### 禁止在运行时变更对象布局
...@@ -137,7 +137,7 @@ let p6 = new Point(6.0, 6.0) ...@@ -137,7 +137,7 @@ let p6 = new Point(6.0, 6.0)
console.log("Distance between p5 and p6: " + distance(p5, p6)) console.log("Distance between p5 and p6: " + distance(p5, p6))
``` ```
不可预测的对象布局修改会影响代码的可读性以及运行时性能。从开发者的角度来说,在某处定义类,然后又在其他地方修改实际的对象布局,很容易引起困惑乃至引入错误。此外,这点还需要额外的运行时支持,增加了执行开销。这一点与静态类型的约束也冲突:既然已决定使用显式类型,为什么还需要添加或删除属性呢? 修改对象布局会影响代码的可读性以及运行时性能。从开发者的角度来说,在某处定义类,然后又在其他地方修改实际的对象布局,很容易引起困惑乃至引入错误。此外,这点还需要额外的运行时支持,增加了执行开销。这一点与静态类型的约束也冲突:既然已决定使用显式类型,为什么还需要添加或删除属性呢?
当前,只有少数项目允许在运行时变更对象布局,一些常用的代码检查工具也增加了相应的限制规则。这个约束只会导致少量代码重构,但对性能提升会有积极的影响。 当前,只有少数项目允许在运行时变更对象布局,一些常用的代码检查工具也增加了相应的限制规则。这个约束只会导致少量代码重构,但对性能提升会有积极的影响。
...@@ -214,13 +214,13 @@ structural typing是否有助于生成清晰、易理解的代码,关于这一 ...@@ -214,13 +214,13 @@ structural typing是否有助于生成清晰、易理解的代码,关于这一
## 约束说明 ## 约束说明
### 仅支持属性名称为标识符的对象 ### 对象的属性名必须是合法的标识符
**规则:**`arkts-identifiers-as-prop-names` **规则:**`arkts-identifiers-as-prop-names`
**级别:错误** **级别:错误**
ArkTS不支持属性名称为数字或字符串的对象。通过属性名访问类的属性,通过数值索引访问数组元素。 在ArkTS中,对象的属性名不能为数字或字符串。通过属性名访问类的属性,通过数值索引访问数组元素。
**TypeScript** **TypeScript**
...@@ -235,9 +235,9 @@ console.log(x[2]) ...@@ -235,9 +235,9 @@ console.log(x[2])
```typescript ```typescript
class X { class X {
public name: number public name: number = 0
} }
let x = {name: 1} let x: X = {name: 1}
console.log(x.name) console.log(x.name)
let y = [1, 2, 3] let y = [1, 2, 3]
...@@ -269,7 +269,7 @@ console.log(z.get(2)) ...@@ -269,7 +269,7 @@ console.log(z.get(2))
**级别:错误** **级别:错误**
TypeScript中的`Symbol()` API用于在运行时生成唯一的属性名称。由于该API的常见使用场景在静态类型语言中没有意义,因此,ArkTS不支持`Symbol()` API。在ArkTS中,对象布局在编译时就确定了,且不能在运行时被更改。 TypeScript中的`Symbol()`API用于在运行时生成唯一的属性名称。由于该API的常见使用场景在静态类型语言中没有意义,因此,ArkTS不支持`Symbol()`API。在ArkTS中,对象布局在编译时就确定了,且不能在运行时被更改。
**TypeScript** **TypeScript**
...@@ -284,7 +284,7 @@ let o = { ...@@ -284,7 +284,7 @@ let o = {
```typescript ```typescript
class SomeClass { class SomeClass {
public someProperty : string public someProperty : string = ""
} }
let o = new SomeClass() let o = new SomeClass()
``` ```
...@@ -300,13 +300,13 @@ let o = new SomeClass() ...@@ -300,13 +300,13 @@ let o = new SomeClass()
* 不支持声明动态属性 * 不支持声明动态属性
* 限制使用标准库 * 限制使用标准库
### 不支持带“#”符号的私有修饰符 ### 不支持以`#`开头的私有字段
**规则:**`arkts-no-private-identifiers` **规则:**`arkts-no-private-identifiers`
**级别:错误** **级别:错误**
ArkTS不支持`#`符号开头的私有修饰符。改用 `private`关键字。 ArkTS不支持使用`#`符号开头声明的私有字段。改用`private`关键字。
**TypeScript** **TypeScript**
...@@ -330,7 +330,7 @@ class C { ...@@ -330,7 +330,7 @@ class C {
**级别:错误** **级别:错误**
类型、命名空间等的命名必须唯一,且能够与变量名等其他名称区分开来。 类型、命名空间等的命名必须唯一,且能够与其他名称(例如:变量名)区分开来。
**TypeScript** **TypeScript**
...@@ -401,57 +401,39 @@ scoped_var = 5 ...@@ -401,57 +401,39 @@ scoped_var = 5
scoped_let = 5 //编译时错误 scoped_let = 5 //编译时错误
``` ```
### 使用具体的类型而非`any`、`undefined`或`unknown` ### 使用具体的类型而非`any`或`unknown`
**规则:**`arkts-no-any-undefined-unknown` **规则:**`arkts-no-any-unknown`
**级别:错误** **级别:错误**
ArkTS不支持`any``undefined``unknown`类型。显式指定具体类型。 ArkTS不支持`any``unknown`类型。显式指定具体类型。
**TypeScript** **TypeScript**
```typescript ```typescript
var x let value1 : any
console.log(x) // undefined value1 = true
value1 = 42
var y: any let value2 : unknown
console.log(y) // undefined value2 = true
value2 = 42
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
// 所有变量都应显式指定其具体类型: let value_b: boolean = true // 或者 let value_b = true
let x: Object = {} let value_n: number = 42 // 或者 let value_n = 42
console.log(x) // {} let value_o1: Object = true
let value_o2: Object = 42
``` ```
**相关约束** **相关约束**
* 使用Object[]而非tuple * 使用Object[]而非tuple
### `bigint`不是内置类型,不支持带后缀`n`的数字字面量
**规则:**`arkts-no-n-suffix`
**级别:错误**
在ArkTS中,`bigint`是标准库的一部分,而非一种内置类型。不支持带后缀`n`的数字字面量。使用`BigInt`工厂函数生成`bigint`类型的值。
**TypeScript**
```typescript
let a: bigint = 1n
```
**ArkTS**
```typescript
let a = BigInt(1)
let b: bigint = BigInt(2)
```
### 使用`Object[]`而非tuple ### 使用`Object[]`而非tuple
**规则:**`arkts-no-tuples` **规则:**`arkts-no-tuples`
...@@ -476,7 +458,7 @@ let n = t[0] ...@@ -476,7 +458,7 @@ let n = t[0]
let s = t[1] let s = t[1]
``` ```
### 使用`class` 而非具有call signature的类型 ### 使用`class`而非具有call signature的类型
**规则:**`arkts-no-call-signatures` **规则:**`arkts-no-call-signatures`
...@@ -519,15 +501,15 @@ doSomething(new DescribableFunction()) ...@@ -519,15 +501,15 @@ doSomething(new DescribableFunction())
**相关约束** **相关约束**
* 使用class而非具有构造函数签名的类型 * 使用class而非具有构造签名的类型
### 使用`class`而非具有构造函数签名的类型 ### 使用`class`而非具有构造签名的类型
**规则:**`arkts-no-ctor-signatures-type` **规则:**`arkts-no-ctor-signatures-type`
**级别:错误** **级别:错误**
ArkTS不支持对象类型中的构造函数签名。改用类。 ArkTS不支持对象类型中的构造签名。改用类。
**TypeScript** **TypeScript**
...@@ -626,7 +608,7 @@ const secondItem = myArray[1] ...@@ -626,7 +608,7 @@ const secondItem = myArray[1]
```typescript ```typescript
class X { class X {
public f: string[] public f: string[] = []
} }
let myArray: X = new X() let myArray: X = new X()
...@@ -673,13 +655,13 @@ interface Contact { ...@@ -673,13 +655,13 @@ interface Contact {
interface Employee extends Identity, Contact {} interface Employee extends Identity, Contact {}
``` ```
### 不支持返回`this`类型 ### 不支持`this`类型
**规则:**`arkts-no-this-as-return-type` **规则:**`arkts-no-typing-with-this`
**级别:错误** **级别:错误**
ArkTS不支持返回`this`类型。改用显式具体类型。 ArkTS不支持`this`类型。改用显式具体类型。
**TypeScript** **TypeScript**
...@@ -687,6 +669,14 @@ ArkTS不支持返回`this`类型。改用显式具体类型。 ...@@ -687,6 +669,14 @@ ArkTS不支持返回`this`类型。改用显式具体类型。
interface ListItem { interface ListItem {
getHead(): this getHead(): this
} }
class C {
n: number = 0
m(c: this) {
console.log(c)
}
}
``` ```
**ArkTS** **ArkTS**
...@@ -695,6 +685,14 @@ interface ListItem { ...@@ -695,6 +685,14 @@ interface ListItem {
interface ListItem { interface ListItem {
getHead(): ListItem getHead(): ListItem
} }
class C {
n: number = 0
m(c: C) {
console.log(c)
}
}
``` ```
### 不支持条件类型 ### 不支持条件类型
...@@ -726,42 +724,6 @@ type X2<T> = Object ...@@ -726,42 +724,6 @@ type X2<T> = Object
type YI<Item, T extends Array<Item>> = Item type YI<Item, T extends Array<Item>> = Item
``` ```
### 可选参数不能使用primitive type
**规则:**`arkts-no-opt-params`
**级别:错误**
ArkTS中,可选参数的类型不能为primitive type。可以使用默认参数或引用类型。对于引用类型,可选参数缺省值为`null`
**TypeScript**
```typescript
// x为可选参数:
function f(x?: number) {
console.log(x) // 打印undefined或某个数字
}
// x为带默认值的必选参数:
function g(x: number = 1) {
console.log(x)
}
```
**ArkTS**
```typescript
// 使用引用类型(缺省值为null):
function f(x?: Number) {
console.log(x) // 打印null或某个数字
}
// 使用带默认值的必选参数:
function g(x: number = 1) {
console.log(x)
}
```
### 不支持在`constructor`中声明字段 ### 不支持在`constructor`中声明字段
**规则:**`arkts-no-ctor-prop-decls` **规则:**`arkts-no-ctor-prop-decls`
...@@ -810,13 +772,13 @@ class Person { ...@@ -810,13 +772,13 @@ class Person {
} }
``` ```
### 接口中不支持构造函数签名 ### 接口中不支持构造签名
**规则:**`arkts-no-ctor-signatures-iface` **规则:**`arkts-no-ctor-signatures-iface`
**级别:错误** **级别:错误**
ArkTS不支持接口中的构造函数签名。改用方法。 ArkTS不支持在接口中使用构造签名。改用函数或者方法。
**TypeScript** **TypeScript**
...@@ -844,7 +806,7 @@ function fn(i: I) { ...@@ -844,7 +806,7 @@ function fn(i: I) {
**相关约束** **相关约束**
* 使用class而非具有构造函数签名的类型 * 使用class而非具有构造签名的类型
### 不支持索引访问类型 ### 不支持索引访问类型
...@@ -874,7 +836,7 @@ type N = number ...@@ -874,7 +836,7 @@ type N = number
**级别:错误** **级别:错误**
ArkTS不支持针对类字段的索引访问。改用点操作符。 ArkTS不支持通过索引访问对象的字段。改用点操作符。
**TypeScript** **TypeScript**
...@@ -1044,7 +1006,7 @@ interface Z { ...@@ -1044,7 +1006,7 @@ interface Z {
foo: number foo: number
} }
// X实现了接口Z,显化定义了X和Y之间的关系。 // X实现了接口Z,显化定义了X和Y之间的关系。
class X implements Z { class X implements Z {
public foo: number public foo: number
...@@ -1053,7 +1015,7 @@ class X implements Z { ...@@ -1053,7 +1015,7 @@ class X implements Z {
} }
} }
// Y实现了接口Z,显化定义了X和Y之间的关系。 // Y实现了接口Z,显化定义了X和Y之间的关系。
class Y implements Z { class Y implements Z {
public foo: number public foo: number
...@@ -1078,60 +1040,13 @@ x = y // ok,两者类型相同 ...@@ -1078,60 +1040,13 @@ x = y // ok,两者类型相同
* 子类型/父类型不支持structural typing * 子类型/父类型不支持structural typing
* 类型推断不支持structural typing * 类型推断不支持structural typing
### 可选属性的的类型不能为primitive type ### 显式标注泛型函数类型实参,除非可以从参数中推断出类型实参
**规则:**`arkts-no-opt-props`
**级别:错误**
ArkTS中,可选属性的类型不能为primitive type。使用默认值或引用类型。对于引用类型,可选属性缺省值为`null`。该规则同样适用于类和接口。
**TypeScript**
```typescript
class CompilerOptions {
strict?: boolean
sourcePath?: string
targetPath?: string
}
let options: CompilerOptions = {
strict: true,
sourcePath: "./src"
}
if (options.targetPath == undefined) {
// 一些代码
}
```
**ArkTS**
```typescript
class CompilerOptions {
strict: boolean = false
sourcePath: string = ""
targetPath?: string
}
let options: CompilerOptions = {
strict: true,
sourcePath: "./src"
// targetPath的值为null
}
if (options.targetPath == null) {
// 一些代码
}
```
### 显式标注泛型函数类型实参,除非可以推断出类型实参
**规则:**`arkts-no-inferred-generic-params` **规则:**`arkts-no-inferred-generic-params`
**级别:错误** **级别:错误**
如果可以从传递给泛型函数的参数中推断出具体类型,ArkTS允许省略泛型类型实参。否则,会发生编译时错误。禁止仅基于函数返回类型推断泛型类型参数。 如果可以从传递给泛型函数的参数中推断出具体类型,ArkTS允许省略泛型类型实参。否则,省略泛型类型实参会发生编译时错误。禁止仅基于泛型函数返回类型推断泛型类型参数。
**TypeScript** **TypeScript**
...@@ -1146,7 +1061,7 @@ let y = choose("10", 20) // 编译时错误 ...@@ -1146,7 +1061,7 @@ let y = choose("10", 20) // 编译时错误
function greet<T>(): T { function greet<T>(): T {
return "Hello" as T return "Hello" as T
} }
let z = greet() // x的类型被推断为“unknown” let z = greet() // T的类型被推断为“unknown”
``` ```
**ArkTS** **ArkTS**
...@@ -1277,17 +1192,17 @@ let regex: RegExp = /bc*d/ ...@@ -1277,17 +1192,17 @@ let regex: RegExp = /bc*d/
let regex: RegExp = new RegExp("/bc*d/") let regex: RegExp = new RegExp("/bc*d/")
``` ```
### 对象字面量必须对应显式声明的类或接口 ### 显式标注对象字面量的类型
**规则:**`arkts-no-untyped-obj-literals` **规则:**`arkts-no-untyped-obj-literals`
**级别:错误** **级别:错误**
如果编译器可以推断对象字面量对应于哪些类或接口,则可以使用对象字面量。否则,将发生编译时错误。具体来说,在以下上下文中不支持使用字面量初始化类和接口: 显式标注对象字面量的类型,除非编译器可以根据上下文推断出字面量的类型是某些类或者接口。否则,将发生编译时错误。具体来说,在以下上下文中不支持使用字面量初始化类和接口:
* 初始化具有`any``Object``object`类型的任何对象 * 初始化具有`any``Object``object`类型的任何对象
* 初始化带有方法的类或接口 * 初始化带有方法的类或接口
* 初始化有自定义且有参数的构造函数的类 * 初始化包含自定义含参数的构造函数的类
* 初始化带`readonly`字段的类 * 初始化带`readonly`字段的类
**TypeScript** **TypeScript**
...@@ -1334,7 +1249,7 @@ function id_x_y(o: Point): Point { ...@@ -1334,7 +1249,7 @@ function id_x_y(o: Point): Point {
return o return o
} }
// structural typing用于推断p为Point // 因为TS支持structural typing,编译器可以推断p的类型为Point
let p = {x: 5, y: 10} let p = {x: 5, y: 10}
id_x_y(p) id_x_y(p)
...@@ -1401,7 +1316,7 @@ function id_x_y(o: Point): Point { ...@@ -1401,7 +1316,7 @@ function id_x_y(o: Point): Point {
let p: Point = {x: 5, y: 10} let p: Point = {x: 5, y: 10}
id_x_y(p) id_x_y(p)
// id_x_y预计接受Point类型,字面量初始化生成一个Point的新实例 // id_x_y接受Point类型,字面量初始化生成一个Point的新实例
id_x_y({x: 5, y: 10}) id_x_y({x: 5, y: 10})
``` ```
...@@ -1416,7 +1331,7 @@ id_x_y({x: 5, y: 10}) ...@@ -1416,7 +1331,7 @@ id_x_y({x: 5, y: 10})
**级别:错误** **级别:错误**
ArkTS不支持使用对象字面量声明类型。需显式声明类和接口 ArkTS不支持使用对象字面量声明类型,可以使用类或者接口声明类型
**TypeScript** **TypeScript**
...@@ -1433,8 +1348,8 @@ type S = Set<{x: number, y: number}> ...@@ -1433,8 +1348,8 @@ type S = Set<{x: number, y: number}>
```typescript ```typescript
class O { class O {
x: number x: number = 0
y: number y: number = 0
} }
let o: O = {x: 2, y: 3} let o: O = {x: 2, y: 3}
...@@ -1453,7 +1368,7 @@ type S = Set<O> ...@@ -1453,7 +1368,7 @@ type S = Set<O>
**级别:错误** **级别:错误**
本质上,ArkTS将数组字面量的类型推断为数组内容的联合类型。如果其中任何一个元素的类型无法根据上下文推导出来(例如,未类型化的对象字面量),则会发生编译时错误。 本质上,ArkTS将数组字面量的类型推断为数组所有元素的联合类型。如果其中任何一个元素的类型无法根据上下文推导出来(例如,无类型的对象字面量),则会发生编译时错误。
**TypeScript** **TypeScript**
...@@ -1474,11 +1389,10 @@ let a2: C[] = [{n: 1, s: "1"}, {n: 2, s : "2"}] // a2的类型为“C[]” ...@@ -1474,11 +1389,10 @@ let a2: C[] = [{n: 1, s: "1"}, {n: 2, s : "2"}] // a2的类型为“C[]”
``` ```
**相关约束** **相关约束**
* 对象字面量必须对应某些显式声明的类或接口 * 对象字面量必须对应某些显式声明的类或接口
* 对象字面量不能用于类型声明 * 对象字面量不能用于类型声明
### Lambda函数的参数类型必须显式化 ### 显式标注Lambda函数的参数类型
**规则:**`arkts-explicit-param-types-in-lambdas` **规则:**`arkts-explicit-param-types-in-lambdas`
...@@ -1489,7 +1403,8 @@ let a2: C[] = [{n: 1, s: "1"}, {n: 2, s : "2"}] // a2的类型为“C[]” ...@@ -1489,7 +1403,8 @@ let a2: C[] = [{n: 1, s: "1"}, {n: 2, s : "2"}] // a2的类型为“C[]”
**TypeScript** **TypeScript**
```typescript ```typescript
let f = (s) => { // 隐式定义类型为any // 只有在开启noImplicitAny选项时会产生编译时错误
let f = (s /* type any is assumed */) => {
console.log(s) console.log(s)
} }
``` ```
...@@ -1497,7 +1412,7 @@ let f = (s) => { // 隐式定义类型为any ...@@ -1497,7 +1412,7 @@ let f = (s) => { // 隐式定义类型为any
**ArkTS** **ArkTS**
```typescript ```typescript
// lambda函数的参数类型必须显式化 // 显式标注Lambda函数的参数类型
let f = (s: string) => { let f = (s: string) => {
console.log(s) console.log(s)
} }
...@@ -1566,11 +1481,11 @@ ArkTS不支持使用类表达式。必须显式声明一个类。 ...@@ -1566,11 +1481,11 @@ ArkTS不支持使用类表达式。必须显式声明一个类。
```typescript ```typescript
const Rectangle = class { const Rectangle = class {
constructor(height: number, width: number) { constructor(height: number, width: number) {
this.heigth = height this.height = height
this.width = width this.width = width
} }
heigth height
width width
} }
...@@ -1582,11 +1497,11 @@ const rectangle = new Rectangle(0.0, 0.0) ...@@ -1582,11 +1497,11 @@ const rectangle = new Rectangle(0.0, 0.0)
```typescript ```typescript
class Rectangle { class Rectangle {
constructor(height: number, width: number) { constructor(height: number, width: number) {
this.heigth = height this.height = height
this.width = width this.width = width
} }
heigth: number height: number
width: number width: number
} }
...@@ -1617,7 +1532,7 @@ class C1 implements C { ...@@ -1617,7 +1532,7 @@ class C1 implements C {
```typescript ```typescript
interface C { interface C {
foo() foo(): void
} }
class C1 implements C { class C1 implements C {
...@@ -1640,7 +1555,7 @@ let person = {name: "Bob", isEmployee: true} ...@@ -1640,7 +1555,7 @@ let person = {name: "Bob", isEmployee: true}
let n = person["name"] let n = person["name"]
let e = person["isEmployee"] let e = person["isEmployee"]
let s = person["office"] // undefined let s = person["office"] // 只有在开启noImplicitAny选项时会产生编译时错误
``` ```
**ArkTS** **ArkTS**
...@@ -1664,7 +1579,7 @@ let s = person.office // 编译时错误 ...@@ -1664,7 +1579,7 @@ let s = person.office // 编译时错误
**相关约束** **相关约束**
* 仅支持属性名称为标识符的对象 * 对象的属性名必须是合法的标识符
* 不支持Symbol() API * 不支持Symbol() API
* 不支持delete运算符 * 不支持delete运算符
* 仅允许在表达式中使用typeof运算符 * 仅允许在表达式中使用typeof运算符
...@@ -1681,6 +1596,8 @@ let s = person.office // 编译时错误 ...@@ -1681,6 +1596,8 @@ let s = person.office // 编译时错误
在ArkTS中,`as`关键字是类型转换的唯一语法。错误的类型转换会导致编译时错误或者运行时抛出`ClassCastException`异常。不支持使用`<type>`语法进行类型转换。 在ArkTS中,`as`关键字是类型转换的唯一语法。错误的类型转换会导致编译时错误或者运行时抛出`ClassCastException`异常。不支持使用`<type>`语法进行类型转换。
当需要将`primitive`类型(如`number``boolean`)转换成引用类型时,请使用`new`表达式。
**TypeScript** **TypeScript**
```typescript ```typescript
...@@ -1699,6 +1616,12 @@ let c2 = createShape() as Circle ...@@ -1699,6 +1616,12 @@ let c2 = createShape() as Circle
// 如果转换错误,不会产生编译时或运行时报错 // 如果转换错误,不会产生编译时或运行时报错
let c3 = createShape() as Square let c3 = createShape() as Square
console.log(c3.y) // undefined console.log(c3.y) // undefined
// 在TS中,由于`as`关键字不会在运行时生效,所以`instanceof`的左操作数不会在运行时被装箱成引用类型
let e1 = (5.0 as Number) instanceof Number // false
// 创建Number对象,获得预期结果:
let e2 = (new Number(5.0)) instanceof Number // true
``` ```
**ArkTS** **ArkTS**
...@@ -1716,6 +1639,9 @@ let c2 = createShape() as Circle ...@@ -1716,6 +1639,9 @@ let c2 = createShape() as Circle
// 运行时抛出ClassCastException异常: // 运行时抛出ClassCastException异常:
let c3 = createShape() as Square let c3 = createShape() as Square
// 创建Number对象,获得预期结果:
let e2 = (new Number(5.0)) instanceof Number // true
``` ```
### 不支持JSX表达式 ### 不支持JSX表达式
...@@ -1732,48 +1658,19 @@ let c3 = createShape() as Square ...@@ -1732,48 +1658,19 @@ let c3 = createShape() as Square
**级别:错误** **级别:错误**
ArkTS仅允许一元运算符用于数值类型,否则会发生编译时错误。与TypeScript不同,ArkTS不支持隐式将字符串转换成数值,必须进行显转换。 ArkTS仅允许一元运算符用于数值类型,否则会发生编译时错误。与TypeScript不同,ArkTS不支持隐式将字符串转换成数值,必须进行显转换。
**TypeScript** **TypeScript**
```typescript ```typescript
let a = +5 // 5为number let a = +5 // 5(number类型)
let b = +"5" // 5为number let b = +"5" // 5(number类型)
let c = -5 // -5为number let c = -5 // -5(number类型)
let d = -"5" // -5为number let d = -"5" // -5(number类型)
let e = ~5 // -6为number let e = ~5 // -6(number类型)
let f = ~"5" // -6为number let f = ~"5" // -6(number类型)
let g = +"string" // NaN为number let g = +"string" // NaN(number类型)
```
**ArkTS**
```typescript
let a = +5 // 5为number
let b = +"5" // 编译时错误
let c = -5 // -5为number
let d = -"5" // 编译时错误
let e = ~5 // -6为number
let f = ~"5" // 编译时错误
let g = +"string" // 编译时错误
```
**相关约束**
* 二元运算符\*、/、%、-、<<、>>、>>>、&、^ 和|仅适用于数值类型
* 二元运算符+仅支持数字和字符串的隐式转换
### 一元运算符`+`不能将任何类型转换为数值类型
**规则:**`arkts-no-unary-plus-cast`
**级别:错误**
ArkTS不支持使用一元运算符`+`将任何类型转换为数值类型,该运算符只能用于数值类型。
**TypeScript**
```typescript
function returnTen(): string { function returnTen(): string {
return "-10" return "-10"
} }
...@@ -1782,13 +1679,21 @@ function returnString(): string { ...@@ -1782,13 +1679,21 @@ function returnString(): string {
return "string" return "string"
} }
let a = +returnTen() // -10为数值 let x = +returnTen() // -10(number类型)
let b = +returnString() // NaN let y = +returnString() // NaN
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
let a = +5 // 5(number类型)
let b = +"5" // 编译时错误
let c = -5 // -5(number类型)
let d = -"5" // 编译时错误
let e = ~5 // -6(number类型)
let f = ~"5" // 编译时错误
let g = +"string" // 编译时错误
function returnTen(): string { function returnTen(): string {
return "-10" return "-10"
} }
...@@ -1797,16 +1702,10 @@ function returnString(): string { ...@@ -1797,16 +1702,10 @@ function returnString(): string {
return "string" return "string"
} }
let a = +returnTen() // 编译时错误 let x = +returnTen() // 编译时错误
let b = +returnString() // 编译时错误 let y = +returnString() // 编译时错误
``` ```
**相关约束**
* 一元运算符+、-和~仅适用于数值类型
* 二元运算符\*、/、%、-、<<、>>、>>>、&、^ 和|仅适用于数值类型
* 二元运算符+仅支持数字和字符串的隐式转换
### 不支持`delete`运算符 ### 不支持`delete`运算符
**规则:**`arkts-no-delete` **规则:**`arkts-no-delete`
...@@ -1832,8 +1731,8 @@ delete p.y ...@@ -1832,8 +1731,8 @@ delete p.y
```typescript ```typescript
// 可以声明一个可空类型并使用null作为缺省值 // 可以声明一个可空类型并使用null作为缺省值
class Point { class Point {
x: number | null x: number | null = 0
y: number | null y: number | null = 0
} }
let p = new Point() let p = new Point()
...@@ -1842,7 +1741,7 @@ p.y = null ...@@ -1842,7 +1741,7 @@ p.y = null
**相关约束** **相关约束**
* 仅支持属性名称为标识符的对象 * 对象的属性名必须是合法的标识符
* 不支持Symbol() API * 不支持Symbol() API
* 访问未定义的属性将导致编译时错误 * 访问未定义的属性将导致编译时错误
* 仅允许在表达式中使用typeof运算符 * 仅允许在表达式中使用typeof运算符
...@@ -1882,7 +1781,7 @@ let s2: string ...@@ -1882,7 +1781,7 @@ let s2: string
**相关约束** **相关约束**
* 仅支持属性名称为标识符的对象 * 对象的属性名必须是合法的标识符
* 不支持Symbol() API * 不支持Symbol() API
* 访问未定义的属性将导致编译时错误 * 访问未定义的属性将导致编译时错误
* 不支持delete运算符 * 不支持delete运算符
...@@ -1891,73 +1790,14 @@ let s2: string ...@@ -1891,73 +1790,14 @@ let s2: string
* 不支持声明动态属性 * 不支持声明动态属性
* 限制使用标准库 * 限制使用标准库
### 二元运算符`*`、`/`、`%`、`-`、`<<`、`>>`、`>>>`、`&`、`^`和`|`仅适用于数值类型 ### 二元运算符`+`仅支持数字和字符串的隐式转换
**规则:**`arkts-no-polymorphic-binops`
**级别:错误**
在ArkTS中,二元运算符`*``/``%``-``<<``>>``>>>``&``^``|`仅可用于数值类型。不支持将其他类型隐式转换为数值类型,否则会导致编译时错误。
**TypeScript**
```typescript
let a = (5 & 5) // 5
let b = (5.5 & 5.5) // 5,非5.5
let c = (5 | 5) // 5
let d = (5.5 | 5.5) // 5,非5.5
enum Direction {
Up = -1,
Down
}
let e = Direction.Up >> 1 // -1
let f = Direction.Up >>> 1 // 2147483647
let g = ("10" as any) << 1 // 20
let h = ("str" as any) << 1 // 0
let i = 10 * 5
let j = 10 / 5
let k = 10 % 5
let l = 10 - 5
```
**ArkTS**
```typescript
let a = (5 & 5) // 5
let b = (5.5 & 5.5) // 编译时错误
let c = (5 | 5) // 5
let d = (5.5 | 5.5) // 编译时错误
enum Direction {
Up,
Down
}
let e = Direction.Up >> 1 // 0
let f = Direction.Up >>> 1 // 0
let i = 10 * 5
let j = 10 / 5
let k = 10 % 5
let l = 10 - 5
```
**相关约束**
* 一元运算符+、-和~仅适用于数值类型
* 一元运算符`+`不能将任何类型转换为数值类型
* 二元运算符+仅支持数字和字符串的隐式转换
### 二元运算符+仅支持数字和字符串的隐式转换
**规则:**`arkts-no-polymorphic-plus` **规则:**`arkts-no-polymorphic-plus`
**级别:错误** **级别:错误**
ArkTS支持使用`+`对字符串和数字进行隐式转换。其他情形下,都需要显式转换为字符串。 如果二元运算符`+`的一个操作数是`string`类型(包括enum中的`string`),那么另一个操作数可以是任意的类型,在运算时它的值被隐式转换成`string`。在其他情况下,ArkTS只支持`number`和enum中的`number`的隐式转换。
正如TypeScript一样,ArkTS不支持两个`boolean`类型的值相加。其他情形下,都需要显式转换为字符串。
**TypeScript** **TypeScript**
...@@ -1973,6 +1813,10 @@ let e = "Hello, " + "world!" // "Hello, world!" ...@@ -1973,6 +1813,10 @@ let e = "Hello, " + "world!" // "Hello, world!"
let f = "string" + true // "stringtrue" let f = "string" + true // "stringtrue"
let g = (new Object()) + "string" // "[object Object]string" let g = (new Object()) + "string" // "[object Object]string"
let i = true + true // JS: 2, TS: 编译时错误
let j = true + 2 // JS: 3, TS: 编译时错误
let k = E.E1 + true // JS: 1, TS: 编译时错误
``` ```
**ArkTS** **ArkTS**
...@@ -1989,13 +1833,15 @@ let e = "Hello, " + "world!" // "Hello, world!" ...@@ -1989,13 +1833,15 @@ let e = "Hello, " + "world!" // "Hello, world!"
let f = "string" + true // "stringtrue" let f = "string" + true // "stringtrue"
let g = (new Object()).toString() + "string" let g = (new Object()).toString() + "string"
let i = true + true // 编译时错误
let j = true + 2 // 编译时错误
let k = E.E1 + true // 编译时错误
``` ```
**相关约束** **相关约束**
* 一元运算符+、-和~仅适用于数值类型 * 一元运算符+、-和~仅适用于数值类型
* 一元运算符`+`不能将任何类型转换为数值类型
* 二元运算符\*、/、%、-、<<、>>、>>>、&、^ 和|仅适用于数值类型
### 部分支持`instanceof`运算符 ### 部分支持`instanceof`运算符
...@@ -2008,31 +1854,27 @@ let g = (new Object()).toString() + "string" ...@@ -2008,31 +1854,27 @@ let g = (new Object()).toString() + "string"
**TypeScript** **TypeScript**
```typescript ```typescript
class X {} class X {
// ...
}
let a = (new X()) instanceof Object // true let a = (new X()) instanceof Object // true
let b = (new X()) instanceof X // true let b = (new X()) instanceof X // true
// 左操作数是类型 let c = X instanceof Object // true, 左操作数是一个类型
let c = X instanceof Object // true let d = X instanceof X // false, 左操作数是一个类型
let d = X instanceof X // false
// 左操作数的类型不是any类型
let e = (5.0 as Number) instanceof Number // false
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
class X {} class X {
// ...
}
let a = (new X()) instanceof Object // true let a = (new X()) instanceof Object // true
let b = (new X()) instanceof X // true let b = (new X()) instanceof X // true
// 左操作数是类型 let c = X instanceof Object // 编译时错误, 左操作数是一个类型
let c = X instanceof Object // 编译时错误 let d = X instanceof X // 编译时错误, 左操作数是一个类型
let d = X instanceof X // 编译时错误
// 左操作数可以为任何引用类型,如Number
let e = (5.0 as Number) instanceof Number // true
``` ```
### 不支持`in`运算符 ### 不支持`in`运算符
...@@ -2067,7 +1909,7 @@ let b = p instanceof Person // true,且属性name一定存在 ...@@ -2067,7 +1909,7 @@ let b = p instanceof Person // true,且属性name一定存在
**相关约束** **相关约束**
* 仅支持属性名称为标识符的对象 * 对象的属性名必须是合法的标识符
* 不支持Symbol() API * 不支持Symbol() API
* 访问未定义的属性将导致编译时错误 * 访问未定义的属性将导致编译时错误
* 不支持delete运算符 * 不支持delete运算符
...@@ -2105,11 +1947,11 @@ let tmp = one ...@@ -2105,11 +1947,11 @@ let tmp = one
one = two one = two
two = tmp two = tmp
let data: Number[] = [1,2,3,4] let data: Number[] = [1, 2, 3, 4]
let head = data[0] let head = data[0]
let tail = new Array(data.length - 1) let tail: Number[] = []
for (let i = 1; i < data.length; ++i) { for (let i = 1; i < data.length; ++i) {
tail[i - 1] = data[i] tail.push(data[i])
} }
``` ```
...@@ -2221,7 +2063,7 @@ let c1 = arr[2] ...@@ -2221,7 +2063,7 @@ let c1 = arr[2]
**级别:错误** **级别:错误**
在TypeScript的catch语句中,只能标注类型为`any``unknown`。由于ArkTS不支持这些类型,应省略类型注释 在TypeScript的catch语句中,只能标注`any``unknown`类型。由于ArkTS不支持这些类型,应省略类型标注
**TypeScript** **TypeScript**
...@@ -2229,7 +2071,9 @@ let c1 = arr[2] ...@@ -2229,7 +2071,9 @@ let c1 = arr[2]
try { try {
// 一些代码 // 一些代码
} }
catch (a: unknown) {} catch (a: unknown) {
// 处理异常
}
``` ```
**ArkTS** **ArkTS**
...@@ -2238,7 +2082,9 @@ catch (a: unknown) {} ...@@ -2238,7 +2082,9 @@ catch (a: unknown) {}
try { try {
// 一些代码 // 一些代码
} }
catch (a) {} catch (a) {
// 处理异常
}
``` ```
**相关约束** **相关约束**
...@@ -2278,11 +2124,11 @@ for (let i = 0; i < a.length; ++i) { ...@@ -2278,11 +2124,11 @@ for (let i = 0; i < a.length; ++i) {
### 不支持可迭代接口 ### 不支持可迭代接口
**规则:**`arkts-noiterable` **规则:**`arkts-no-iterable`
**级别:错误** **级别:错误**
ArkTS不支持`Symbol` API、`Symbol.iterator`和最终可迭代的接口。请使用数组和标准库中的容器。 ArkTS不支持`Symbol`API、`Symbol.iterator`和最终可迭代的接口。请使用数组和标准库中的容器。
**相关约束** **相关约束**
...@@ -2311,7 +2157,7 @@ for (let s of a) { ...@@ -2311,7 +2157,7 @@ for (let s of a) {
```typescript ```typescript
let a: Set<number> = new Set([1, 2, 3]) let a: Set<number> = new Set([1, 2, 3])
let numbers = a.values() let numbers = Array.from(a.values())
for (let n of numbers) { for (let n of numbers) {
console.log(n) console.log(n)
} }
...@@ -2364,6 +2210,22 @@ class CFlags { ...@@ -2364,6 +2210,22 @@ class CFlags {
ArkTS不支持`with`语句。使用其他语法来表示相同的语义。 ArkTS不支持`with`语句。使用其他语法来表示相同的语义。
**TypeScript**
```typescript
with (Math) { // 编译时错误, 但是仍能生成JavaScript代码
let r: number = 42
console.log("Area: ", PI * r * r)
}
```
**ArkTS**
```typescript
let r: number = 42
console.log("Area: ", Math.PI * r * r)
```
### `case`语句仅支持编译期值 ### `case`语句仅支持编译期值
**规则:**`arkts-no-computed-case` **规则:**`arkts-no-computed-case`
...@@ -2417,7 +2279,7 @@ switch (x) { ...@@ -2417,7 +2279,7 @@ switch (x) {
**级别:错误** **级别:错误**
ArkTS支持`switch`语句中使用`number`, `Number`, `string`, `String` 或者`enum`类型的值。其他情况下请使用`if`语句。 ArkTS支持`switch`语句中使用`number`, `Number`, `string`, `String`或者`enum`类型的值。其他情况下请使用`if`语句。
**TypeScript** **TypeScript**
...@@ -2483,6 +2345,7 @@ ArkTS在部分场景中支持对函数返回类型进行推断。当`return`语 ...@@ -2483,6 +2345,7 @@ ArkTS在部分场景中支持对函数返回类型进行推断。当`return`语
**TypeScript** **TypeScript**
```typescript ```typescript
// 只有在开启noImplicitAny选项时会产生编译时错误
function f(x: number) { function f(x: number) {
if (x <= 0) { if (x <= 0) {
return x return x
...@@ -2490,6 +2353,7 @@ function f(x: number) { ...@@ -2490,6 +2353,7 @@ function f(x: number) {
return g(x) return g(x)
} }
// 只有在开启noImplicitAny选项时会产生编译时错误
function g(x: number) { function g(x: number) {
return f(x - 1) return f(x - 1)
} }
...@@ -2513,7 +2377,7 @@ function f(x: number) : number { ...@@ -2513,7 +2377,7 @@ function f(x: number) : number {
return g(x) return g(x)
} }
// 需标注返回类型: // 可以省略返回类型,返回类型可以从f的类型标注推导得到
function g(x: number) : number { function g(x: number) : number {
return f(x - 1) return f(x - 1)
} }
...@@ -2617,7 +2481,7 @@ ArkTS不支持在函数中使用`this`。只能在方法中使用`this`。 ...@@ -2617,7 +2481,7 @@ ArkTS不支持在函数中使用`this`。只能在方法中使用`this`。
```typescript ```typescript
function foo(i: number) { function foo(i: number) {
this.count = i this.count = i // 只有在开启noImplicitThis选项时会产生编译时错误
} }
class A { class A {
...@@ -2884,7 +2748,7 @@ console.log(p3d.x, p3d.y, p3d.z) ...@@ -2884,7 +2748,7 @@ console.log(p3d.x, p3d.y, p3d.z)
### 接口不能继承具有相同属性的两个接口 ### 接口不能继承具有相同属性的两个接口
**规则:**`arkts-no-extend-same-property` **规则:**`arkts-no-extend-same-prop`
**级别:错误** **级别:错误**
...@@ -3051,7 +2915,7 @@ interface SelectableControl extends Control { ...@@ -3051,7 +2915,7 @@ interface SelectableControl extends Control {
**级别:错误** **级别:错误**
ArkTS中,对象布局在编译时就确定了,且不能在运行时被更改。禁止运行时检查对象属性。使用`as`运算符进行类型转换以读取相应的属性和方法。读取对象中不存在的属性将导致编译时错误。 ArkTS中,对象布局在编译时就确定了,且不能在运行时被更改。禁止运行时检查对象属性。使用`as`运算符进行类型转换以访问相应的属性和方法。访问对象中不存在的属性将导致编译时错误。
**TypeScript** **TypeScript**
...@@ -3096,7 +2960,7 @@ function main(): void { ...@@ -3096,7 +2960,7 @@ function main(): void {
**相关约束** **相关约束**
* 仅支持属性名称为标识符的对象 * 对象的属性名必须是合法的标识符
* 不支持Symbol() API * 不支持Symbol() API
* 访问未定义的属性将导致编译时错误 * 访问未定义的属性将导致编译时错误
* 不支持delete运算符 * 不支持delete运算符
...@@ -3203,7 +3067,7 @@ function main(): void { ...@@ -3203,7 +3067,7 @@ function main(): void {
**相关约束** **相关约束**
* 仅支持属性名称为标识符的对象 * 对象的属性名必须是合法的标识符
* 不支持Symbol() API * 不支持Symbol() API
* 访问未定义的属性将导致编译时错误 * 访问未定义的属性将导致编译时错误
* 不支持delete运算符 * 不支持delete运算符
...@@ -3323,25 +3187,6 @@ namespace MyNamespace { ...@@ -3323,25 +3187,6 @@ namespace MyNamespace {
MyNamespace.x = 2 MyNamespace.x = 2
``` ```
### 脚本和模块
**规则:**`arkts-no-scripts`
**级别:错误**
通常来说,ArkTS中的脚本和模块与TypeScript非常接近。它们的差异在另外的约束中描述。
**相关约束**
* 不支持import type
* 不支持仅为副作用而导入一个模块
* 不支持import default as ...
* 不支持require
* 不支持重命名导出
* 不支持导出列表
* 不支持重导出
* 不支持通过export = ...
### 不支持命名空间中的非声明语句 ### 不支持命名空间中的非声明语句
**规则:**`arkts-no-ns-statements` **规则:**`arkts-no-ns-statements`
...@@ -3386,23 +3231,23 @@ ArkTS不支持`import type`。改为`import`。 ...@@ -3386,23 +3231,23 @@ ArkTS不支持`import type`。改为`import`。
```typescript ```typescript
// 通用导入语法 // 通用导入语法
import { APIResponseType } from "./api" import { APIResponseType } from "api"
// 导入类型 // 导入类型
import type { APIResponseType } from "./api" import type { APIResponseType } from "api"
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
import { APIResponseType } from "./api" import { APIResponseType } from "api"
``` ```
**相关约束** **相关约束**
* 不支持仅为副作用而导入一个模块 * 不支持仅为副作用而导入一个模块
* 不支持import default as ... * 不支持import default as ...
* 不支持require * 不支持require和import赋值表达式
### 不支持仅为副作用而导入一个模块 ### 不支持仅为副作用而导入一个模块
...@@ -3437,7 +3282,7 @@ import * from "path/to/module" ...@@ -3437,7 +3282,7 @@ import * from "path/to/module"
**级别:错误** **级别:错误**
ArkTS不支持`import default as ...` 语法。使用显式的`import ... from ...` 语法。 ArkTS不支持`import default as ...`语法。使用显式的`import ... from ...`语法。
**TypeScript** **TypeScript**
...@@ -3451,13 +3296,13 @@ import { default as d } from "mod" ...@@ -3451,13 +3296,13 @@ import { default as d } from "mod"
import d from "mod" import d from "mod"
``` ```
### 不支持`require` ### 不支持`require`和`import`赋值表达式
**规则:**`arkts-no-require` **规则:**`arkts-no-require`
**级别:错误** **级别:错误**
ArkTS不支持通过`require`导入。改用`import` ArkTS不支持通过`require`导入,也不支持`import`赋值表达式。改用`import`
**TypeScript** **TypeScript**
...@@ -3471,110 +3316,34 @@ import m = require("mod") ...@@ -3471,110 +3316,34 @@ import m = require("mod")
import * as m from "mod" import * as m from "mod"
``` ```
### 不支持重命名导出
**规则:**`arkts-no-export-renaming`
**级别:错误**
ArkTS不支持重命名导出。可以采用设置别名的方式。
**TypeScript**
```typescript
// file1.ts
class MyClass {
// ...
}
export { MyClass as RenamedClass }
// file2.ts
import { RenamedClass } from "./file1"
function main(): void {
const myObject = new RenamedClass()
// ...
}
```
**ArkTS**
```typescript
// module1
class MyClass {
// ...
}
export type RenamedClass = MyClass
// module2
import { RenamedClass } from "./module1"
function main(): void {
const myObject = new RenamedClass()
// ...
}
```
**相关约束**
* 不支持导出列表
* 不支持重导出
* 不支持通过export = ...
### 不支持导出列表
**规则:**`arkts-no-export-list-decl`
**级别:错误**
ArkTS不支持导出列表的语法。使用`export`关键字显式导出每个值。
**TypeScript**
```typescript
export { x }
export { x } from "mod"
export { x, y as b, z as c }
```
**ArkTS**
```typescript
let x = 1
class MyClass {}
export let y = x, z: number = 2
export type RenamedClass = MyClass
```
**相关约束** **相关约束**
* 不支持重命名导出 * 不支持export = ...语法
* 不支持重导出
* 不支持通过export = ...
### 支持重导出 ### 部分支持重导出
**规则:**`arkts-no-reexport` **规则:**`arkts-limited-reexport`
**级别:错误** **级别:错误**
ArkTS不支持重导出。从导出模块显式导入 ArkTS支持大多数场景下的重导出,比如命名导出和重命名导出,重导出import的。不支持`export * as ...`
**TypeScript** **TypeScript**
```typescript ```typescript
// module1 // module1
export class MyClass { export class Class1 {
// ...
}
export class Class2 {
// ... // ...
} }
// module2 // module2
export { MyClass } from "module1" export * as utilities from "module1"
// consumer模块 // consumer模块
import { MyClass } from "module2" import { utilities } from "module2"
const myInstance = new MyClass() const myInstance = new MyClass()
``` ```
...@@ -3583,27 +3352,28 @@ const myInstance = new MyClass() ...@@ -3583,27 +3352,28 @@ const myInstance = new MyClass()
```typescript ```typescript
// module1 // module1
export class MyClass { export class Class1 {
// ...
}
export class Class2 {
// ... // ...
} }
// module2 // module2
// some stuff export { Class1 } from "module1"
export { C2 as Class2 } from "module1"
// consumer模块 // consumer模块
import { MyClass } from "module1" import { Class1, Class2 } from "module2"
import * from "module2"
const myInstance = new MyClass() const myInstance = new MyClass()
``` ```
**相关约束** **相关约束**
* 不支持重命名导出 * 不支持export = ...语法
* 不支持导出列表
* 不支持通过export = ...
### 不支持通过`export = ...` ### 不支持`export = ...`语法
**规则:**`arkts-no-export-assignment` **规则:**`arkts-no-export-assignment`
...@@ -3645,9 +3415,8 @@ let p = Pt.origin ...@@ -3645,9 +3415,8 @@ let p = Pt.origin
**相关约束** **相关约束**
* 不支持重命名导出 * 不支持require和import赋值表达式
* 不支持导出列表 * 部分支持重导出
* 不支持重导出
### 不支持`export type` ### 不支持`export type`
**规则:**`arkts-no-special-exports` **规则:**`arkts-no-special-exports`
...@@ -3659,14 +3428,32 @@ ArkTS不支持`export type`。改用`export`。 ...@@ -3659,14 +3428,32 @@ ArkTS不支持`export type`。改用`export`。
**TypeScript** **TypeScript**
```typescript ```typescript
class C {} // 显式导出class:
export type { C } export class Class1 {
// ...
}
// 声明一个类,之后通过`export type`导出
class Class2 {
// ...
}
// 不支持
export type { Class2 }
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
export class C {} // 显式导出class:
export class Class1 {
// ...
}
// 显式导出class:
export class Class2 {
// ...
}
``` ```
### 不支持ambient module声明 ### 不支持ambient module声明
...@@ -3689,7 +3476,7 @@ declare module "someModule" { ...@@ -3689,7 +3476,7 @@ declare module "someModule" {
```typescript ```typescript
// 从原始模块中导入需要的内容 // 从原始模块中导入需要的内容
import { normalize } from "../someModule" import { normalize } from "someModule"
``` ```
**相关约束** **相关约束**
...@@ -3708,10 +3495,25 @@ import { normalize } from "../someModule" ...@@ -3708,10 +3495,25 @@ import { normalize } from "../someModule"
**TypeScript** **TypeScript**
```typescript ```typescript
// 声明
declare module "*!text" { declare module "*!text" {
const content: string const content: string
export default content export default content
} }
import fileContent from "some.txt!text"
```
**ArkTS**
```typescript
// 声明
declare namespace N {
function foo(x: number): number
}
import * from "module"
console.log("N.foo called: ", N.foo(42))
``` ```
**相关约束** **相关约束**
...@@ -3748,7 +3550,7 @@ namespace mathLib { ...@@ -3748,7 +3550,7 @@ namespace mathLib {
} }
// 程序中 // 程序中
import { mathLib } from "./math-lib" import { mathLib } from "math-lib"
mathLib.isPrime(2) mathLib.isPrime(2)
``` ```
...@@ -3767,13 +3569,13 @@ ArkTS不允许在模块标识符中使用`.js`扩展名,因为ArkTS本身有 ...@@ -3767,13 +3569,13 @@ ArkTS不允许在模块标识符中使用`.js`扩展名,因为ArkTS本身有
**TypeScript** **TypeScript**
```typescript ```typescript
import { something } from "./module.js" import { something } from "module.js"
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
import { something } from "./module" import { something } from "module"
``` ```
**相关约束** **相关约束**
...@@ -3803,6 +3605,19 @@ class CustomError extends Error { ...@@ -3803,6 +3605,19 @@ class CustomError extends Error {
} }
``` ```
**ArkTS**
```typescript
class CustomError extends Error {
constructor(message?: string) {
// 调用父类构造函数,继承链是静态的,且不能在运行时被改变
super(message)
console.log(this instanceof Error) // true
}
}
let ce = new CustomError()
```
**相关约束** **相关约束**
* 不支持在原型上赋值 * 不支持在原型上赋值
...@@ -3818,13 +3633,13 @@ class CustomError extends Error { ...@@ -3818,13 +3633,13 @@ class CustomError extends Error {
**TypeScript** **TypeScript**
```typescript ```typescript
const zipUtil = await import("./utils/create-zip-file") const zipUtil = await import("utils/create-zip-file")
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
import { zipUtil } from "./utils/create-zip-file" import { zipUtil } from "utils/create-zip-file"
``` ```
**相关约束** **相关约束**
...@@ -3867,7 +3682,7 @@ let x: number = initialize() ...@@ -3867,7 +3682,7 @@ let x: number = initialize()
console.log("x = " + x) console.log("x = " + x)
``` ```
### 不支持IIFE作为命名空间的声明 ### 不支持IIFE(立即调用函数表达式)作为命名空间的声明
**规则:**`arkts-no-iife` **规则:**`arkts-no-iife`
...@@ -3879,9 +3694,10 @@ console.log("x = " + x) ...@@ -3879,9 +3694,10 @@ console.log("x = " + x)
```typescript ```typescript
var C = (function() { var C = (function() {
function C(n) { function C(n: number) {
this.p = n this.p = n // 只有在开启noImplicitThis选项时会产生编译时错误
} }
C.staticProperty = 0
return C return C
})() })()
C.staticProperty = 1 C.staticProperty = 1
...@@ -3907,7 +3723,7 @@ ArkTS没有原型的概念,因此不支持在原型上赋值。此特性不符 ...@@ -3907,7 +3723,7 @@ ArkTS没有原型的概念,因此不支持在原型上赋值。此特性不符
```typescript ```typescript
var C = function(p) { var C = function(p) {
this.p = p this.p = p // 只有在开启noImplicitThis选项时会产生编译时错误
} }
C.prototype = { C.prototype = {
...@@ -3916,8 +3732,22 @@ C.prototype = { ...@@ -3916,8 +3732,22 @@ C.prototype = {
} }
} }
C.prototype.q = function(r) { C.prototype.q = function(r: number) {
return this.p === r return this.p == r
}
```
**ArkTS**
```typescript
class C {
p: number = 0
m() {
console.log(this.p)
}
q(r: number) {
return this.p == r
}
} }
``` ```
...@@ -3939,7 +3769,7 @@ C.prototype.q = function(r) { ...@@ -3939,7 +3769,7 @@ C.prototype.q = function(r) {
// 全局文件中 // 全局文件中
var abc = 100 var abc = 100
// 从上面引用'abc' // 从上面引用'abc'
globalThis.abc = 200 globalThis.abc = 200
``` ```
...@@ -3950,7 +3780,7 @@ globalThis.abc = 200 ...@@ -3950,7 +3780,7 @@ globalThis.abc = 200
export let abc : number = 0 export let abc : number = 0
// file2 // file2
import * as M from "../file1" import * as M from "file1"
M.abc = 200 M.abc = 200
``` ```
...@@ -3960,13 +3790,16 @@ M.abc = 200 ...@@ -3960,13 +3790,16 @@ M.abc = 200
* 不支持声明函数的属性 * 不支持声明函数的属性
* 标准库使用限制 * 标准库使用限制
### 不支持utility类型 ### 不支持一些utility类型
**规则:**`arkts-no-utility-types` **规则:**`arkts-no-utility-types`
**级别:错误** **级别:错误**
当前ArkTS不支持从TypeScript扩展到标准库的utility类型(例如`Omit``Partial``Readonly``Record``Pick`等)。 当前ArkTS不支持从TypeScript扩展到标准库的utility类型(例如`Omit``Pick`等)。支持`Partial``Record`
对于*Record<K, V>*类型,表达式*rec[index]*的类型是*V | undefined*
对于`Record`类型,键-值中的值的类型必须是可选类型或者包含`undefined`的联合类型。
**TypeScript** **TypeScript**
...@@ -3978,20 +3811,55 @@ type Person = { ...@@ -3978,20 +3811,55 @@ type Person = {
} }
type QuantumPerson = Omit<Person, "location"> type QuantumPerson = Omit<Person, "location">
let persons : Record<string, Person> = {
"Alice": {
name: "Alice",
age: 32,
location: "Shanghai"
},
"Bob": {
name: "Bob",
age: 48,
location: "New York"
}
}
console.log(persons["Bob"].age)
console.log(persons["Rob"].age) // 运行时异常
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
class Person { class Person {
name: string name: string = ""
age: number age: number = 0
location: string location: string = ""
} }
class QuantumPerson { class QuantumPerson {
name: string name: string = ""
age: number age: number = 0
}
type OptionalPerson = Person | undefined
let persons : Record<string, OptionalPerson> = {
// 或者
// let persons : Record<string, Person | undefined> = {
"Alice": {
name: "Alice",
age: 32,
location: "Shanghai"
},
"Bob": {
name: "Bob",
age: 48,
location: "New York"
}
}
console.log(persons["Bob"]!.age)
if (persons["Rob"]) { // 值检查,不会运行时抛异常
console.log(persons["Rob"].age)
} }
``` ```
...@@ -4038,15 +3906,15 @@ class MyImage { ...@@ -4038,15 +3906,15 @@ class MyImage {
// ... // ...
} }
function readImage( async function readImage(
path: string, callback: (err: Error, image: MyImage) => void path: string, callback: (err: Error, image: MyImage) => void
) : Promise<MyImage> ) : Promise<MyImage>
{ {
// 异步实现 return await new MyImage()
} }
function readImageSync(path: string) : MyImage { function readImageSync(path: string) : MyImage {
// 同步实现 return new MyImage()
} }
``` ```
...@@ -4165,7 +4033,7 @@ let x : string = "hello" ...@@ -4165,7 +4033,7 @@ let x : string = "hello"
let y : number[] = [10, 20] let y : number[] = [10, 20]
class Label { class Label {
text : string text : string = ""
} }
// 'Label'类型 // 'Label'类型
...@@ -4185,14 +4053,14 @@ let z : Label = { ...@@ -4185,14 +4053,14 @@ let z : Label = {
**TypeScript** **TypeScript**
```typescript ```typescript
import { obj } from "./something.json" assert { type: "json" } import { obj } from "something.json" assert { type: "json" }
``` ```
**ArkTS** **ArkTS**
```typescript ```typescript
// 编译时将检查导入T的正确性 // 编译时将检查导入T的正确性
import { something } from "./module" import { something } from "module"
``` ```
**相关约束** **相关约束**
...@@ -4241,7 +4109,7 @@ ArkTS不允许使用TypeScript或JavaScript标准库中的某些接口。大部 ...@@ -4241,7 +4109,7 @@ ArkTS不允许使用TypeScript或JavaScript标准库中的某些接口。大部
**相关约束** **相关约束**
* 仅支持属性名称为标识符的对象 * 对象的属性名必须是合法的标识符
* 不支持Symbol() API * 不支持Symbol() API
* 访问未定义的属性将导致编译时错误 * 访问未定义的属性将导致编译时错误
* 仅允许在表达式中使用typeof运算符 * 仅允许在表达式中使用typeof运算符
...@@ -4249,3 +4117,153 @@ ArkTS不允许使用TypeScript或JavaScript标准库中的某些接口。大部 ...@@ -4249,3 +4117,153 @@ ArkTS不允许使用TypeScript或JavaScript标准库中的某些接口。大部
* 禁止运行时检查对象属性 * 禁止运行时检查对象属性
* 不支持声明动态属性 * 不支持声明动态属性
* 不支持globalThis * 不支持globalThis
### 强制开启严格类型检查
**规则 `arkts-strict-typing`**
**级别:错误**
在ArkTS中,以下TypeScript的严格类型检查选项必须打开:`noImplicitReturns`,
`strictFunctionTypes`, `strictNullChecks`, `strictPropertyInitialization`
**TypeScript**
```typescript
class C {
n: number // 只有在开启strictPropertyInitialization选项时会产生编译时错误
s: string // 只有在开启strictPropertyInitialization选项时会产生编译时错误
}
// 只有在开启noImplicitReturns选项时会产生编译时错误
function foo(s: string): string {
if (s != "") {
console.log(s)
return s
} else {
console.log(s)
}
}
let n: number = null // 只有在开启strictNullChecks选项时会产生编译时错误
```
**ArkTS**
```typescript
class C {
n: number = 0
s: string = ""
}
function foo(s: string): string {
console.log(s)
return s
}
let n1: number | null = null
let n2: number = 0
```
**相关约束**
* 使用具体的类型而非any或unknown
* 不允许通过注释关闭类型检查
### 不允许通过注释关闭类型检查
**规则 `arkts-strict-typing-required`**
**级别:错误**
在ArkTS中,类型检查不是可选项。不允许通过注释关闭类型检查,不支持使用`@ts-ignore``@ts-nocheck`
**TypeScript**
```typescript
// @ts-nocheck
// ...
// 关闭了类型检查后的代码
// ...
let s1: string = null // 没有报错
// @ts-ignore
let s2: string = null // 没有报错
```
**ArkTS**
```typescript
let s1: string | null = null // 没有报错,合适的类型
let s2: string = null // 编译时报错
```
**相关约束**
* 使用具体的类型而非any或unknown
* 强制开启严格类型检查
### 允许ArkTS代码导入TS代码, 不允许TS代码导入ArkTS代码
**规则 `arkts-no-ts-deps`**
**级别:错误**
ArkTS中的代码可以导入来自标准TypeScript的代码,而标准TypeScript的代码不能导入来自ArkTS中的代码。
**TypeScript**
```typescript
// app.ets
export class C {
// ...
}
// lib.ts
import { C } from "app"
```
**ArkTS**
```typescript
// lib1.ets
export class C {
// ...
}
// lib2.ets
import { C } from "lib1"
```
### 除了ArkUI中的装饰器,不允许使用其他装饰器
**规则 `arkts-no-decorators-except-arkui`**
**级别:错误**
现在,ArkTS中只支持ArkUI中的装饰器。使用其他装饰器会造成编译时错误。
**TypeScript**
```typescript
function classDecorator(x: number, y: number): void {
//
}
@classDecorator
class BugReport {
}
```
**ArkTS**
```typescript
function classDecorator(x: number, y: number): void {
//
}
@classDecorator // 编译时错误
class BugReport {
}
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册