• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 从TypeScript到ArkTS的适配规则
2
3ArkTS规范约束了TypeScript(简称TS)中影响开发正确性或增加运行时开销的特性。本文罗列了ArkTS中限制的TS特性,并提供重构代码的建议。ArkTS保留了TS大部分语法特性,未在本文中约束的TS特性,ArkTS完全支持。例如,ArkTS支持自定义装饰器,语法与TS一致。按本文约束进行代码重构后,代码仍为合法有效的TS代码。
4
5**示例**
6
7包含关键字`var`的原始TypeScript代码:
8
9```typescript
10function addTen(x: number): number {
11  var ten = 10;
12  return x + ten;
13}
14```
15
16重构后的代码:
17
18```typescript
19function addTen(x: number): number {
20  let ten = 10;
21  return x + ten;
22}
23```
24
25**级别**
26
27约束分为两个级别:错误、警告。
28
29- **错误**: 必须要遵从的约束。如果不遵从该约束,将会导致程序编译失败。
30- **警告**: 推荐遵从的约束。尽管现在违反该约束不会影响编译流程,但是在将来,违反该约束可能将会导致程序编译失败。
31
32**不支持的特性**
33
34目前,不支持的特性主要包括:
35
36- 与降低运行时性能的动态类型相关的特性。
37- 需要编译器额外支持从而导致项目构建时间增加的特性。
38
39根据开发者的反馈和实际场景的数据,将来会进一步减少不支持的特性。
40
41## 概述
42
43本节罗列了ArkTS不支持或部分支持的TypeScript特性。完整的列表以及详细的代码示例和重构建议,请参考[约束说明](#约束说明)。更多案例请参考[适配指导案例](arkts-more-cases.md)。
44
45### 强制使用静态类型
46
47静态类型是ArkTS的重要特性之一。当程序使用静态类型时,所有类型在编译时已知,这有助于开发者理解代码中的数据结构。编译器可以提前验证代码的正确性,减少运行时的类型检查,从而提升性能。
48
49基于上述考虑,ArkTS中禁止使用`any`类型。
50
51**示例**
52
53```typescript
54// 不支持:
55let res: any = some_api_function('hello', 'world');
56// `res`是什么?错误代码的数字?字符串?对象?
57// 该如何处理它?
58// 支持:
59class CallResult {
60  public succeeded(): boolean { ... }
61  public errorMessage(): string { ... }
62}
63
64let res: CallResult = some_api_function('hello', 'world');
65if (!res.succeeded()) {
66  console.log('Call failed: ' + res.errorMessage());
67}
68```
69
70`any`类型在TypeScript中并不常见,仅约1%的TypeScript代码库使用。代码检查工具(例如ESLint)也制定了一系列规则来禁止使用`any`。因此,虽然禁止`any`将导致代码重构,但重构量很小,有助于整体性能提升。
71
72### 禁止在运行时变更对象布局
73
74为实现最佳性能,ArkTS要求在程序执行期间不能更改对象的布局。换句话说,ArkTS禁止以下行为:
75
76- 向对象中添加新的属性或方法。
77- 从对象中删除已有的属性或方法。
78- 将任意类型的值赋值给对象属性。
79
80TypeScript编译器已经禁止了许多此类操作。然而,有些操作还是有可能绕过编译器的,例如,使用`as any`转换对象的类型,或者在编译TS代码时关闭严格类型检查的配置,或者在代码中通过`@ts-ignore`忽略类型检查。
81
82在ArkTS中,严格类型检查不是可配置项。ArkTS强制进行部分严格类型检查,并通过规范禁止使用`any`类型,禁止在代码中使用`@ts-ignore`。
83
84**示例**
85
86```typescript
87class Point {
88  public x: number = 0
89  public y: number = 0
90
91  constructor(x: number, y: number) {
92    this.x = x;
93    this.y = y;
94  }
95}
96
97// 无法从对象中删除某个属性,从而确保所有Point对象都具有属性x
98let p1 = new Point(1.0, 1.0);
99delete p1.x;           // 在TypeScript和ArkTS中,都会产生编译时错误
100delete (p1 as any).x;  // 在TypeScript中不会报错;在ArkTS中会产生编译时错误
101
102// Point类没有定义命名为z的属性,在程序运行时也无法添加该属性
103let p2 = new Point(2.0, 2.0);
104p2.z = 'Label';           // 在TypeScript和ArkTS中,都会产生编译时错误
105(p2 as any).z = 'Label';   // 在TypeScript中不会报错;在ArkTS中会产生编译时错误
106
107// 类的定义确保了所有Point对象只有属性x和y,并且无法被添加其他属性
108let p3 = new Point(3.0, 3.0);
109let prop = Symbol();      // 在TypeScript中不会报错;在ArkTS中会产生编译时错误
110(p3 as any)[prop] = p3.x; // 在TypeScript中不会报错;在ArkTS中会产生编译时错误
111p3[prop] = p3.x;          // 在TypeScript和ArkTS中,都会产生编译时错误
112
113// 类的定义确保了所有Point对象的属性x和y都具有number类型,因此,无法将其他类型的值赋值给它们
114let p4 = new Point(4.0, 4.0);
115p4.x = 'Hello!';          // 在TypeScript和ArkTS中,都会产生编译时错误
116(p4 as any).x = 'Hello!'; // 在TypeScript中不会报错;在ArkTS中会产生编译时错误
117
118// 使用符合类定义的Point对象:
119function distance(p1: Point, p2: Point): number {
120  return Math.sqrt(
121    (p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y)
122  );
123}
124let p5 = new Point(5.0, 5.0);
125let p6 = new Point(6.0, 6.0);
126console.log('Distance between p5 and p6: ' + distance(p5, p6));
127```
128
129修改对象布局会影响代码可读性和运行时性能。定义类后,在其他地方修改对象布局,容易引起困惑乃至引入错误。此外,还需要额外的运行时支持,增加执行开销。这与静态类型约束冲突:使用显式类型时,不应添加或删除属性。
130
131当前,只有少数项目允许在运行时变更对象布局,一些常用的代码检查工具也增加了相应的限制规则。这个约束只会导致少量代码重构,但会提升性能。
132
133### 限制运算符的语义
134
135为获得更好的性能并鼓励开发者编写更清晰的代码,ArkTS限制了一些运算符的语义。详细的语义限制,请参考[约束说明](#约束说明)。
136
137**示例**
138
139```typescript
140// 一元运算符`+`只能作用于数值类型:
141let t = +42;   // 合法运算
142let s = +'42'; // 编译时错误
143```
144
145使用额外的语义重载语言运算符会增加语言规范的复杂度,而且,开发者还被迫牢记所有可能的例外情况及对应的处理规则。在特定情况下,这会导致不必要的运行时开销。
146
147当前只有不到1%的代码库使用该特性。因此,尽管限制运算符的语义需要重构代码,但重构量很小且非常容易操作,并且,通过重构能使代码更清晰、具备更高性能。
148
149### 不支持 structural typing
150
151假设两个不相关的类`T`和`U`拥有相同的`public`API:
152
153```typescript
154class T {
155  public name: string = ''
156
157  public greet(): void {
158    console.log('Hello, ' + this.name);
159  }
160}
161
162class U {
163  public name: string = ''
164
165  public greet(): void {
166    console.log('Greetings, ' + this.name);
167  }
168}
169```
170
171类型为`T`的值是否能赋给类型为`U`的变量。
172
173```typescript
174let u: U = new T(); // 是否允许?
175```
176
177类型为`T`的值是否能传递给接受类型为`U`的参数的函数。
178
179```typescript
180function greeter(u: U) {
181  console.log('To ' + u.name);
182  u.greet();
183}
184
185let t: T = new T();
186greeter(t); // 是否允许?
187```
188
189具体采用哪种方法,情况如下:
190
191- `T`和`U`没有继承关系或没有`implements`相同的接口,但由于它们具有相同的`public`API,它们“在某种程度上是相等的”,所以上述两个问题的答案都是“是”。
192- `T`和`U`没有继承关系或没有`implements`相同的接口,应当始终被视为完全不同的类型,因此上述两个问题的答案都是“否”。
193
194采用第一种方法的语言支持structural typing,而采用第二种方法的语言则不支持structural typing。目前TypeScript支持structural typing,而ArkTS不支持。
195
196关于structural typing是否有助于生成清晰、易理解的代码,目前尚未有定论。ArkTS不支持structural typing的原因如下:
197
198因为对structural typing的支持是一个重大的特性,需要在语言规范、编译器和运行时进行大量的考虑和仔细的实现。另外,由于ArkTS使用静态类型,运行时为了支持这个特性需要额外的性能开销。
199
200鉴于此,当前我们还不支持该特性。根据实际场景的需求和反馈,我们后续会重新加以考虑。更多案例和建议请参考[约束说明](#约束说明)。
201
202## 约束说明
203
204### 对象的属性名必须是合法的标识符
205
206**规则:**`arkts-identifiers-as-prop-names`
207
208**级别:错误**
209
210**错误码:10605001**
211
212在ArkTS中,对象的属性名不能为数字或字符串。例外:ArkTS支持属性名为字符串字面量和枚举中的字符串值。通过属性名访问类的属性,通过数值索引访问数组元素。
213
214**TypeScript**
215
216```typescript
217var x = { 'name': 'x', 2: '3' };
218
219console.log(x['name']);
220console.log(x[2]);
221```
222
223**ArkTS**
224
225```typescript
226class X {
227  public name: string = ''
228}
229let x: X = { name: 'x' };
230console.log(x.name);
231
232let y = ['a', 'b', 'c'];
233console.log(y[2]);
234
235// 在需要通过非标识符(即不同类型的key)获取数据的场景中,使用Map<Object, some_type>。
236let z = new Map<Object, string>();
237z.set('name', '1');
238z.set(2, '2');
239console.log(z.get('name'));
240console.log(z.get(2));
241
242enum Test {
243  A = 'aaa',
244  B = 'bbb'
245}
246
247let obj: Record<string, number> = {
248  [Test.A]: 1,   // 枚举中的字符串值
249  [Test.B]: 2,   // 枚举中的字符串值
250  ['value']: 3   // 字符串字面量
251}
252```
253
254### 不支持`Symbol()`API
255
256**规则:**`arkts-no-symbol`
257
258**级别:错误**
259
260**错误码:10605002**
261
262在ArkTS中,对象布局在编译时确定,不可在运行时更改,因此不支持`Symbol()`API。该API在静态类型语言中通常没有实际意义。
263
264ArkTS只支持`Symbol.iterator`。
265
266### 不支持以`#`开头的私有字段
267
268**规则:**`arkts-no-private-identifiers`
269
270**级别:错误**
271
272**错误码:10605003**
273
274ArkTS不支持使用`#`符号开头声明的私有字段。改用`private`关键字。
275
276**TypeScript**
277
278```typescript
279class C {
280  #foo: number = 42
281}
282```
283
284**ArkTS**
285
286```typescript
287class C {
288  private foo: number = 42
289}
290```
291
292### 类型、命名空间的命名必须唯一
293
294**规则:**`arkts-unique-names`
295
296**级别:错误**
297
298**错误码:10605004**
299
300类型(类、接口、枚举)和命名空间的名称必须唯一,并且不能与其他名称(如变量名、函数名)重复。
301
302**TypeScript**
303
304```typescript
305let X: string
306type X = number[] // 类型的别名与变量同名
307```
308
309**ArkTS**
310
311```typescript
312let X: string
313type T = number[] // 为避免名称冲突,此处不允许使用X
314```
315
316### 使用`let`而非`var`
317
318**规则:**`arkts-no-var`
319
320**级别:错误**
321
322**错误码:10605005**
323
324`let`关键字可以在块级作用域中声明变量,帮助程序员避免错误。因此,ArkTS不支持`var`,请使用`let`声明变量。
325
326**TypeScript**
327
328```typescript
329function f(shouldInitialize: boolean) {
330  if (shouldInitialize) {
331     var x = 'b';
332  }
333  return x;
334}
335
336console.log(f(true));  // b
337console.log(f(false)); // undefined
338
339let upperLet = 0;
340{
341  var scopedVar = 0;
342  let scopedLet = 0;
343  upperLet = 5;
344}
345scopedVar = 5; // 可见
346scopedLet = 5; // 编译时错误
347```
348
349**ArkTS**
350
351```typescript
352function f(shouldInitialize: boolean): string {
353  let x: string = 'a';
354  if (shouldInitialize) {
355    x = 'b';
356  }
357  return x;
358}
359
360console.log(f(true));  // b
361console.log(f(false)); // a
362
363let upperLet = 0;
364let scopedVar = 0;
365{
366  let scopedLet = 0;
367  upperLet = 5;
368}
369scopedVar = 5;
370scopedLet = 5; //编译时错误
371```
372
373### 使用具体的类型而非`any`或`unknown`
374
375**规则:**`arkts-no-any-unknown`
376
377**级别:错误**
378
379**错误码:10605008**
380
381ArkTS不支持`any`和`unknown`类型。显式指定具体类型。
382
383**TypeScript**
384
385```typescript
386let value1: any
387value1 = true;
388value1 = 42;
389
390let value2: unknown
391value2 = true;
392value2 = 42;
393```
394
395**ArkTS**
396
397```typescript
398let value_b: boolean = true; // 或者 let value_b = true
399let value_n: number = 42; // 或者 let value_n = 42
400let value_o1: Object = true;
401let value_o2: Object = 42;
402```
403
404### 使用`class`而非具有call signature的类型
405
406**规则:**`arkts-no-call-signatures`
407
408**级别:错误**
409
410**错误码:10605014**
411
412ArkTS不支持对象类型中包含call signature。
413
414**TypeScript**
415
416```typescript
417type DescribableFunction = {
418  description: string
419  (someArg: string): string // call signature
420}
421
422function doSomething(fn: DescribableFunction): void {
423  console.log(fn.description + ' returned ' + fn(''));
424}
425```
426
427**ArkTS**
428
429```typescript
430class DescribableFunction {
431  description: string
432  public invoke(someArg: string): string {
433    return someArg;
434  }
435  constructor() {
436    this.description = 'desc';
437  }
438}
439
440function doSomething(fn: DescribableFunction): void {
441  console.log(fn.description + ' returned ' + fn.invoke(''));
442}
443
444doSomething(new DescribableFunction());
445```
446
447### 使用`class`而非具有构造签名的类型
448
449**规则:**`arkts-no-ctor-signatures-type`
450
451**级别:错误**
452
453**错误码:10605015**
454
455ArkTS不支持对象类型中的构造签名。改用类。
456
457**TypeScript**
458
459```typescript
460class SomeObject {}
461
462type SomeConstructor = {
463  new (s: string): SomeObject
464}
465
466function fn(ctor: SomeConstructor) {
467  return new ctor('hello');
468}
469```
470
471**ArkTS**
472
473```typescript
474class SomeObject {
475  public f: string
476  constructor (s: string) {
477    this.f = s;
478  }
479}
480
481function fn(s: string): SomeObject {
482  return new SomeObject(s);
483}
484```
485
486### 仅支持一个静态块
487
488**规则:**`arkts-no-multiple-static-blocks`
489
490**级别:错误**
491
492**错误码:10605016**
493
494ArkTS不允许类中有多个静态块,如果存在多个静态块语句,请合并到一个静态块中。
495
496**TypeScript**
497
498```typescript
499class C {
500  static s: string
501
502  static {
503    C.s = 'aa'
504  }
505  static {
506    C.s = C.s + 'bb'
507  }
508}
509```
510
511**ArkTS**
512
513```typescript
514class C {
515  static s: string
516
517  static {
518    C.s = 'aa'
519    C.s = C.s + 'bb'
520  }
521}
522```
523
524**说明**
525
526当前不支持静态块的语法。支持该语法后,在.ets文件中使用静态块需遵循此约束。
527
528### 不支持index signature
529
530**规则:**`arkts-no-indexed-signatures`
531
532**级别:错误**
533
534**错误码:10605017**
535
536ArkTS不允许index signature,改用数组。
537
538**TypeScript**
539
540```typescript
541// 带index signature的接口:
542interface StringArray {
543  [index: number]: string
544}
545
546function getStringArray(): StringArray {
547  return ['a', 'b', 'c'];
548}
549
550const myArray: StringArray = getStringArray();
551const secondItem = myArray[1];
552```
553
554**ArkTS**
555
556```typescript
557class X {
558  public f: string[] = []
559}
560
561let myArray: X = new X();
562const secondItem = myArray.f[1];
563```
564
565### 使用继承而非intersection type
566
567**规则:**`arkts-no-intersection-types`
568
569**级别:错误**
570
571**错误码:10605019**
572
573目前ArkTS不支持intersection type,可以使用继承作为替代方案。
574
575**TypeScript**
576
577```typescript
578interface Identity {
579  id: number
580  name: string
581}
582
583interface Contact {
584  email: string
585  phoneNumber: string
586}
587
588type Employee = Identity & Contact
589```
590
591**ArkTS**
592
593```typescript
594interface Identity {
595  id: number
596  name: string
597}
598
599interface Contact {
600  email: string
601  phoneNumber: string
602}
603
604interface Employee extends Identity,  Contact {}
605```
606
607### 不支持`this`类型
608
609**规则:**`arkts-no-typing-with-this`
610
611**级别:错误**
612
613**错误码:10605021**
614
615ArkTS不支持`this`类型,改用显式具体类型。
616
617**TypeScript**
618
619```typescript
620interface ListItem {
621  getHead(): this
622}
623
624class C {
625  n: number = 0
626
627  m(c: this) {
628    // ...
629  }
630}
631```
632
633**ArkTS**
634
635```typescript
636interface ListItem {
637  getHead(): ListItem
638}
639
640class C {
641  n: number = 0
642
643  m(c: C) {
644    // ...
645  }
646}
647```
648
649### 不支持条件类型
650
651**规则:**`arkts-no-conditional-types`
652
653**级别:错误**
654
655**错误码:10605022**
656
657ArkTS不支持条件类型别名,建议引入带显式约束的新类型,或使用`Object`进行逻辑重构。
658不支持`infer`关键字。
659
660**TypeScript**
661
662```typescript
663type X<T> = T extends number ? T: never
664type Y<T> = T extends Array<infer Item> ? Item: never
665```
666
667**ArkTS**
668
669```typescript
670// 在类型别名中提供显式约束
671type X1<T extends number> = T
672
673// 用Object重写,类型控制较少,需要更多的类型检查以确保安全
674type X2<T> = Object
675
676// Item必须作为泛型参数使用,并能正确实例化
677type YI<Item, T extends Array<Item>> = Item
678```
679
680### 不支持在`constructor`中声明字段
681
682**规则:**`arkts-no-ctor-prop-decls`
683
684**级别:错误**
685
686**错误码:10605025**
687
688ArkTS不支持在`constructor`中声明类字段。在`class`中声明这些字段。
689
690**TypeScript**
691
692```typescript
693class Person {
694  constructor(
695    protected ssn: string,
696    private firstName: string,
697    private lastName: string
698  ) {
699    this.ssn = ssn;
700    this.firstName = firstName;
701    this.lastName = lastName;
702  }
703
704  getFullName(): string {
705    return this.firstName + ' ' + this.lastName;
706  }
707}
708```
709
710**ArkTS**
711
712```typescript
713class Person {
714  protected ssn: string
715  private firstName: string
716  private lastName: string
717
718  constructor(ssn: string, firstName: string, lastName: string) {
719    this.ssn = ssn;
720    this.firstName = firstName;
721    this.lastName = lastName;
722  }
723
724  getFullName(): string {
725    return this.firstName + ' ' + this.lastName;
726  }
727}
728```
729
730### 接口中不支持构造签名
731
732**规则:**`arkts-no-ctor-signatures-iface`
733
734**级别:错误**
735
736**错误码:10605027**
737
738ArkTS不支持在接口中使用构造签名。建议使用函数或方法。
739
740**TypeScript**
741
742```typescript
743interface I {
744  new (s: string): I
745}
746
747function fn(i: I) {
748  return new i('hello');
749}
750```
751
752**ArkTS**
753
754```typescript
755interface I {
756  create(s: string): I
757}
758
759function fn(i: I) {
760  return i.create('hello');
761}
762```
763
764### 不支持索引访问类型
765
766**规则:**`arkts-no-aliases-by-index`
767
768**级别:错误**
769
770**错误码:10605028**
771
772ArkTS不支持索引访问类型。
773
774### 不支持通过索引访问字段
775
776**规则:**`arkts-no-props-by-index`
777
778**级别:错误**
779
780**错误码:10605029**
781
782ArkTS不支持动态声明字段,不支持动态访问字段。只能访问已在类中声明或者继承可见的字段,访问其他字段将会造成编译时错误。
783使用点操作符访问字段,例如(`obj.field`),不支持索引访问(`obj[field]`)。
784ArkTS支持通过索引访问`TypedArray`(例如`Int32Array`)中的元素。
785
786**TypeScript**
787
788```typescript
789class Point {
790  x: string = ''
791  y: string = ''
792}
793let p: Point = {x: '1', y: '2'};
794console.log(p['x']);
795
796class Person {
797  name: string = ''
798  age: number = 0;
799  [key: string]: string | number
800}
801
802let person: Person = {
803  name: 'John',
804  age: 30,
805  email: '***@example.com',
806  phoneNumber: '18*********',
807}
808```
809
810**ArkTS**
811
812```typescript
813class Point {
814  x: string = ''
815  y: string = ''
816}
817let p: Point = {x: '1', y: '2'};
818console.log(p.x);
819
820class Person {
821  name: string
822  age: number
823  email: string
824  phoneNumber: string
825
826  constructor(name: string, age: number, email: string,
827        phoneNumber: string) {
828    this.name = name;
829    this.age = age;
830    this.email = email;
831    this.phoneNumber = phoneNumber;
832  }
833}
834
835let person = new Person('John', 30, '***@example.com', '18*********');
836console.log(person['name']);     // 编译时错误
837console.log(person.unknownProperty); // 编译时错误
838
839let arr = new Int32Array(1);
840arr[0];
841```
842
843### 不支持structural typing
844
845**规则:**`arkts-no-structural-typing`
846
847**级别:错误**
848
849**错误码:10605030**
850
851ArkTS不支持structural typing,编译器无法比较两种类型的`public`API并决定它们是否相同。使用其他机制,例如继承、接口或类型别名。
852
853**TypeScript**
854
855```typescript
856interface I1 {
857  f(): string
858}
859
860interface I2 { // I2等价于I1
861  f(): string
862}
863
864class X {
865  n: number = 0
866  s: string = ''
867}
868
869class Y { // Y等价于X
870  n: number = 0
871  s: string = ''
872}
873
874let x = new X();
875let y = new Y();
876
877console.log('Assign X to Y');
878y = x;
879
880console.log('Assign Y to X');
881x = y;
882
883function foo(x: X) {
884  console.log(x.n + x.s);
885}
886
887// 由于X和Y的API是等价的,所以X和Y是等价的
888foo(new X());
889foo(new Y());
890```
891
892**ArkTS**
893
894```typescript
895interface I1 {
896  f(): string
897}
898
899type I2 = I1 // I2是I1的别名
900
901class B {
902  n: number = 0
903  s: string = ''
904}
905
906// D是B的继承类,构建了子类型和父类型的关系
907class D extends B {
908  constructor() {
909    super()
910  }
911}
912
913let b = new B();
914let d = new D();
915
916console.log('Assign D to B');
917b = d; // 合法赋值,因为B是D的父类
918
919// 将b赋值给d将会引起编译时错误
920// d = b
921
922interface Z {
923   n: number
924   s: string
925}
926
927// 类X implements 接口Z,构建了X和Y的关系
928class X implements Z {
929  n: number = 0
930  s: string = ''
931}
932
933// 类Y implements 接口Z,构建了X和Y的关系
934class Y implements Z {
935  n: number = 0
936  s: string = ''
937}
938
939let x: Z = new X();
940let y: Z = new Y();
941
942console.log('Assign X to Y');
943y = x // 合法赋值,它们是相同的类型
944
945console.log('Assign Y to X');
946x = y // 合法赋值,它们是相同的类型
947
948function foo(c: Z): void {
949  console.log(c.n + c.s);
950}
951
952// 类X和类Y implement 相同的接口,因此下面的两个函数调用都是合法的
953foo(new X());
954foo(new Y());
955```
956
957### 需要显式标注泛型函数类型实参
958
959**规则:**`arkts-no-inferred-generic-params`
960
961**级别:错误**
962
963**错误码:10605034**
964
965如果可以从传递给泛型函数的参数中推断出具体类型,ArkTS允许省略泛型类型实参。否则,省略泛型类型实参会发生编译时错误。
966禁止仅基于泛型函数返回类型推断泛型类型参数。
967
968**TypeScript**
969
970```typescript
971function choose<T>(x: T, y: T): T {
972  return Math.random() < 0.5 ? x: y;
973}
974
975let x = choose(10, 20);   // 推断choose<number>(...)
976let y = choose('10', 20); // 编译时错误
977
978function greet<T>(): T {
979  return 'Hello' as T;
980}
981let z = greet() // T的类型被推断为“unknown”
982```
983
984**ArkTS**
985
986```typescript
987function choose<T>(x: T, y: T): T {
988  return Math.random() < 0.5 ? x: y;
989}
990
991let x = choose(10, 20);   // 推断choose<number>(...)
992let y = choose('10', 20); // 编译时错误
993
994function greet<T>(): T {
995  return 'Hello' as T;
996}
997let z = greet<string>();
998```
999
1000### 需要显式标注对象字面量的类型
1001
1002**规则:**`arkts-no-untyped-obj-literals`
1003
1004**级别:错误**
1005
1006**错误码:10605038**
1007
1008在ArkTS中,需要显式标注对象字面量的类型,否则,将发生编译时错误。在某些场景下,编译器可以根据上下文推断出字面量的类型。
1009
1010在以下上下文中不支持使用字面量初始化类和接口:
1011
1012* 初始化具有`any`、`Object`或`object`类型的任何对象
1013* 初始化带有方法的类或接口
1014* 初始化包含自定义含参数的构造函数的类
1015* 初始化带`readonly`字段的类
1016
1017**例子1**
1018
1019**TypeScript**
1020
1021```typescript
1022let o1 = {n: 42, s: 'foo'};
1023let o2: Object = {n: 42, s: 'foo'};
1024let o3: object = {n: 42, s: 'foo'};
1025
1026let oo: Object[] = [{n: 1, s: '1'}, {n: 2, s: '2'}];
1027```
1028
1029**ArkTS**
1030
1031```typescript
1032class C1 {
1033  n: number = 0
1034  s: string = ''
1035}
1036
1037let o1: C1 = {n: 42, s: 'foo'};
1038let o2: C1 = {n: 42, s: 'foo'};
1039let o3: C1 = {n: 42, s: 'foo'};
1040
1041let oo: C1[] = [{n: 1, s: '1'}, {n: 2, s: '2'}];
1042```
1043
1044**例子2**
1045
1046**TypeScript**
1047
1048```typescript
1049class C2 {
1050  s: string
1051  constructor(s: string) {
1052    this.s = 's =' + s;
1053  }
1054}
1055let o4: C2 = {s: 'foo'};
1056```
1057
1058**ArkTS**
1059
1060```typescript
1061class C2 {
1062  s: string
1063  constructor(s: string) {
1064    this.s = 's =' + s;
1065  }
1066}
1067let o4 = new C2('foo');
1068```
1069
1070**例子3**
1071
1072**TypeScript**
1073
1074```typescript
1075class C3 {
1076  readonly n: number = 0
1077  readonly s: string = ''
1078}
1079let o5: C3 = {n: 42, s: 'foo'};
1080```
1081
1082**ArkTS**
1083
1084```typescript
1085class C3 {
1086  n: number = 0
1087  s: string = ''
1088}
1089let o5: C3 = {n: 42, s: 'foo'};
1090```
1091
1092**例子4**
1093
1094**TypeScript**
1095
1096```typescript
1097abstract class A {}
1098let o6: A = {};
1099```
1100
1101**ArkTS**
1102
1103```typescript
1104abstract class A {}
1105class C extends A {}
1106let o6: C = {}; // 或 let o6: C = new C()
1107```
1108
1109**例子5**
1110
1111**TypeScript**
1112
1113```typescript
1114class C4 {
1115  n: number = 0
1116  s: string = ''
1117  f() {
1118    console.log('Hello');
1119  }
1120}
1121let o7: C4 = {n: 42, s: 'foo', f: () => {}};
1122```
1123
1124**ArkTS**
1125
1126```typescript
1127class C4 {
1128  n: number = 0
1129  s: string = ''
1130  f() {
1131    console.log('Hello');
1132  }
1133}
1134let o7 = new C4();
1135o7.n = 42;
1136o7.s = 'foo';
1137```
1138
1139**例子6**
1140
1141**TypeScript**
1142
1143```typescript
1144class Point {
1145  x: number = 0
1146  y: number = 0
1147}
1148
1149function getPoint(o: Point): Point {
1150  return o;
1151}
1152
1153// TS支持structural typing,可以推断p的类型为Point
1154let p = {x: 5, y: 10};
1155getPoint(p);
1156
1157// 可通过上下文推断出对象字面量的类型为Point
1158getPoint({x: 5, y: 10});
1159```
1160
1161**ArkTS**
1162
1163```typescript
1164class Point {
1165  x: number = 0
1166  y: number = 0
1167
1168  // 在字面量初始化之前,使用constructor()创建一个有效对象。
1169  // 由于没有为Point定义构造函数,编译器将自动添加一个默认构造函数。
1170}
1171
1172function getPoint(o: Point): Point {
1173  return o;
1174}
1175
1176// 字面量初始化需要显式定义类型
1177let p: Point = {x: 5, y: 10};
1178getPoint(p);
1179
1180// getPoint接受Point类型,字面量初始化生成一个Point的新实例
1181getPoint({x: 5, y: 10});
1182```
1183
1184### 对象字面量不能用于类型声明
1185
1186**规则:**`arkts-no-obj-literals-as-types`
1187
1188**级别:错误**
1189
1190**错误码:10605040**
1191
1192ArkTS不支持使用对象字面量声明类型,可以使用类或者接口声明类型。
1193
1194**TypeScript**
1195
1196```typescript
1197let o: {x: number, y: number} = {
1198  x: 2,
1199  y: 3
1200}
1201
1202type S = Set<{x: number, y: number}>
1203```
1204
1205**ArkTS**
1206
1207```typescript
1208class O {
1209  x: number = 0
1210  y: number = 0
1211}
1212
1213let o: O = {x: 2, y: 3};
1214
1215type S = Set<O>
1216```
1217
1218### 数组字面量必须仅包含可推断类型的元素
1219
1220**规则:**`arkts-no-noninferrable-arr-literals`
1221
1222**级别:错误**
1223
1224**错误码:10605043**
1225
1226ArkTS将数组字面量的类型推断为所有元素的联合类型。如果其中任何一个元素的类型无法推导,则编译时会发生错误。
1227
1228**TypeScript**
1229
1230```typescript
1231let a = [{n: 1, s: '1'}, {n: 2, s: '2'}];
1232```
1233
1234**ArkTS**
1235
1236```typescript
1237class C {
1238  n: number = 0
1239  s: string = ''
1240}
1241
1242let a1 = [{n: 1, s: '1'} as C, {n: 2, s: '2'} as C]; // a1的类型为“C[]”
1243let a2: C[] = [{n: 1, s: '1'}, {n: 2, s: '2'}];    // a2的类型为“C[]”
1244```
1245
1246### 使用箭头函数而非函数表达式
1247
1248**规则:**`arkts-no-func-expressions`
1249
1250**级别:错误**
1251
1252**错误码:10605046**
1253
1254ArkTS不支持函数表达式,使用箭头函数。
1255
1256**TypeScript**
1257
1258```typescript
1259let f = function (s: string) {
1260  console.log(s);
1261}
1262```
1263
1264**ArkTS**
1265
1266```typescript
1267let f = (s: string) => {
1268  console.log(s);
1269}
1270```
1271
1272### 不支持使用类表达式
1273
1274**规则:**`arkts-no-class-literals`
1275
1276**级别:错误**
1277
1278**错误码:10605050**
1279
1280ArkTS不支持类表达式,必须显式声明一个类。
1281
1282**TypeScript**
1283
1284```typescript
1285const Rectangle = class {
1286  constructor(height: number, width: number) {
1287    this.height = height;
1288    this.width = width;
1289  }
1290
1291  height
1292  width
1293}
1294
1295const rectangle = new Rectangle(0.0, 0.0);
1296```
1297
1298**ArkTS**
1299
1300```typescript
1301class Rectangle {
1302  constructor(height: number, width: number) {
1303    this.height = height;
1304    this.width = width;
1305  }
1306
1307  height: number
1308  width: number
1309}
1310
1311const rectangle = new Rectangle(0.0, 0.0);
1312```
1313
1314### 类不允许`implements`
1315
1316**规则:**`arkts-implements-only-iface`
1317
1318**级别:错误**
1319
1320**错误码:10605051**
1321
1322ArkTS不允许类被`implements`,只有接口可以被`implements`。
1323
1324**TypeScript**
1325
1326```typescript
1327class C {
1328  foo() {}
1329}
1330
1331class C1 implements C {
1332  foo() {}
1333}
1334```
1335
1336**ArkTS**
1337
1338```typescript
1339interface C {
1340  foo(): void
1341}
1342
1343class C1 implements C {
1344  foo() {}
1345}
1346```
1347
1348### 不支持修改对象的方法
1349
1350**规则:**`arkts-no-method-reassignment`
1351
1352**级别:错误**
1353
1354**错误码:10605052**
1355
1356ArkTS不支持修改对象的方法。在静态语言中,对象布局固定,类的所有实例共享同一个方法。
1357若需为特定对象添加方法,可封装函数或采用继承机制。
1358
1359**TypeScript**
1360
1361```typescript
1362class C {
1363  foo() {
1364    console.log('foo');
1365  }
1366}
1367
1368function bar() {
1369  console.log('bar');
1370}
1371
1372let c1 = new C();
1373let c2 = new C();
1374c2.foo = bar;
1375
1376c1.foo(); // foo
1377c2.foo(); // bar
1378```
1379
1380**ArkTS**
1381
1382```typescript
1383class C {
1384  foo() {
1385    console.log('foo');
1386  }
1387}
1388
1389class Derived extends C {
1390  foo() {
1391    console.log('Extra');
1392    super.foo();
1393  }
1394}
1395
1396function bar() {
1397  console.log('bar');
1398}
1399
1400let c1 = new C();
1401let c2 = new C();
1402c1.foo(); // foo
1403c2.foo(); // foo
1404
1405let c3 = new Derived();
1406c3.foo(); // Extra foo
1407```
1408
1409### 类型转换仅支持`as T`语法
1410
1411**规则:**`arkts-as-casts`
1412
1413**级别:错误**
1414
1415**错误码:10605053**
1416
1417在ArkTS中,`as`关键字是类型转换的唯一语法,错误的类型转换会导致编译时错误或者运行时抛出`ClassCastException`异常。ArkTS不支持使用`<type>`语法进行类型转换。
1418
1419需要将`primitive`类型(如`number`或`boolean`)转换为引用类型时,请使用`new`表达式。
1420
1421**TypeScript**
1422
1423```typescript
1424class Shape {}
1425class Circle extends Shape { x: number = 5 }
1426class Square extends Shape { y: string = 'a' }
1427
1428function createShape(): Shape {
1429  return new Circle();
1430}
1431
1432let c1 = <Circle> createShape();
1433
1434let c2 = createShape() as Circle;
1435
1436// 如果转换错误,不会产生编译时或运行时报错
1437let c3 = createShape() as Square;
1438console.log(c3.y); // undefined
1439
1440// 在TS中,由于`as`关键字不会在运行时生效,所以`instanceof`的左操作数不会在运行时被装箱成引用类型
1441let e1 = (5.0 as Number) instanceof Number; // false
1442
1443// 创建Number对象,获得预期结果:
1444let e2 = (new Number(5.0)) instanceof Number; // true
1445```
1446
1447**ArkTS**
1448
1449```typescript
1450class Shape {}
1451class Circle extends Shape { x: number = 5 }
1452class Square extends Shape { y: string = 'a' }
1453
1454function createShape(): Shape {
1455  return new Circle();
1456}
1457
1458let c2 = createShape() as Circle;
1459
1460// 运行时抛出ClassCastException异常:
1461let c3 = createShape() as Square;
1462
1463// 创建Number对象,获得预期结果:
1464let e2 = (new Number(5.0)) instanceof Number; // true
1465```
1466
1467### 不支持JSX表达式
1468
1469**规则:**`arkts-no-jsx`
1470
1471**级别:错误**
1472
1473**错误码:10605054**
1474
1475不支持使用JSX。
1476
1477### 一元运算符`+`、`-`和`~`仅适用于数值类型
1478
1479**规则:**`arkts-no-polymorphic-unops`
1480
1481**级别:错误**
1482
1483**错误码:10605055**
1484
1485ArkTS仅允许一元运算符用于数值类型,否则会导致编译时错误。与TypeScript不同,ArkTS不支持隐式字符串到数值的转换,必须进行显式转换。
1486
1487**TypeScript**
1488
1489```typescript
1490let a = +5;    // 5(number类型)
1491let b = +'5';    // 5(number类型)
1492let c = -5;    // -5(number类型)
1493let d = -'5';    // -5(number类型)
1494let e = ~5;    // -6(number类型)
1495let f = ~'5';    // -6(number类型)
1496let g = +'string'; // NaN(number类型)
1497
1498function returnTen(): string {
1499  return '-10';
1500}
1501
1502function returnString(): string {
1503  return 'string';
1504}
1505
1506let x = +returnTen();  // -10(number类型)
1507let y = +returnString(); // NaN
1508```
1509
1510**ArkTS**
1511
1512```typescript
1513let a = +5;    // 5(number类型)
1514let b = +'5';    // 编译时错误
1515let c = -5;    // -5(number类型)
1516let d = -'5';    // 编译时错误
1517let e = ~5;    // -6(number类型)
1518let f = ~'5';    // 编译时错误
1519let g = +'string'; // 编译时错误
1520
1521function returnTen(): string {
1522  return '-10';
1523}
1524
1525function returnString(): string {
1526  return 'string';
1527}
1528
1529let x = +returnTen();  // 编译时错误
1530let y = +returnString(); // 编译时错误
1531```
1532
1533### 不支持`delete`运算符
1534
1535**规则:**`arkts-no-delete`
1536
1537**级别:错误**
1538
1539**错误码:10605059**
1540
1541在ArkTS中,对象布局在编译时确定,运行时不可更改。因此,删除属性的操作没有意义。
1542
1543**TypeScript**
1544
1545```typescript
1546class Point {
1547  x?: number = 0.0
1548  y?: number = 0.0
1549}
1550
1551let p = new Point();
1552delete p.y;
1553```
1554
1555**ArkTS**
1556
1557```typescript
1558// 可以声明一个可空类型并使用null作为缺省值
1559class Point {
1560  x: number | null = 0
1561  y: number | null = 0
1562}
1563
1564let p = new Point();
1565p.y = null;
1566```
1567
1568### 仅允许在表达式中使用`typeof`运算符
1569
1570**规则:**`arkts-no-type-query`
1571
1572**级别:错误**
1573
1574**错误码:10605060**
1575
1576ArkTS仅支持在表达式中使用`typeof`运算符,不允许使用`typeof`作为类型。
1577
1578**TypeScript**
1579
1580```typescript
1581let n1 = 42;
1582let s1 = 'foo';
1583console.log(typeof n1); // 'number'
1584console.log(typeof s1); // 'string'
1585let n2: typeof n1
1586let s2: typeof s1
1587```
1588
1589**ArkTS**
1590
1591```typescript
1592let n1 = 42;
1593let s1 = 'foo';
1594console.log(typeof n1); // 'number'
1595console.log(typeof s1); // 'string'
1596let n2: number
1597let s2: string
1598```
1599
1600### 部分支持`instanceof`运算符
1601
1602**规则:**`arkts-instanceof-ref-types`
1603
1604**级别:错误**
1605
1606**错误码:10605065**
1607
1608TypeScript中,`instanceof`运算符的左操作数类型必须为`any`类型、对象类型或类型参数,否则结果为`false`。ArkTS中,`instanceof`运算符的左操作数类型必须为引用类型(如对象、数组或函数),否则会发生编译时错误。此外,左操作数必须是对象实例。
1609
1610### 不支持`in`运算符
1611
1612**规则:**`arkts-no-in`
1613
1614**级别:错误**
1615
1616**错误码:10605066**
1617
1618在ArkTS中,对象布局在编译时已知且运行时无法修改,因此不支持`in`运算符。需要检查类成员是否存在时,使用`instanceof`代替。
1619
1620**TypeScript**
1621
1622```typescript
1623class Person {
1624  name: string = ''
1625}
1626let p = new Person();
1627
1628let b = 'name' in p; // true
1629```
1630
1631**ArkTS**
1632
1633```typescript
1634class Person {
1635  name: string = ''
1636}
1637let p = new Person();
1638
1639let b = p instanceof Person; // true,且属性name一定存在
1640```
1641
1642### 不支持解构赋值
1643
1644**规则:**`arkts-no-destruct-assignment`
1645
1646**级别:错误**
1647
1648**错误码:10605069**
1649
1650ArkTS不支持解构赋值。可使用其他替代方法,例如,使用临时变量。
1651
1652**TypeScript**
1653
1654```typescript
1655let [one, two] = [1, 2]; // 此处需要分号
1656[one, two] = [two, one];
1657
1658let head, tail
1659[head, ...tail] = [1, 2, 3, 4];
1660```
1661
1662**ArkTS**
1663
1664```typescript
1665let arr: number[] = [1, 2];
1666let one = arr[0];
1667let two = arr[1];
1668
1669let tmp = one;
1670one = two;
1671two = tmp;
1672
1673let data: Number[] = [1, 2, 3, 4];
1674let head = data[0];
1675let tail: Number[] = [];
1676for (let i = 1; i < data.length; ++i) {
1677  tail.push(data[i]);
1678}
1679```
1680
1681### 逗号运算符`,`仅用在`for`循环语句中
1682
1683**规则:**`arkts-no-comma-outside-loops`
1684
1685**级别:错误**
1686
1687**错误码:10605071**
1688
1689在ArkTS中,逗号运算符仅适用于`for`循环语句,用于明确执行顺序。
1690>**注意:** 这与声明变量和函数参数传递时使用的逗号分隔符不同。
1691
1692**TypeScript**
1693
1694```typescript
1695for (let i = 0, j = 0; i < 10; ++i, j += 2) {
1696  // ...
1697}
1698
1699let x = 0;
1700x = (++x, x++); // 1
1701```
1702
1703**ArkTS**
1704
1705```typescript
1706for (let i = 0, j = 0; i < 10; ++i, j += 2) {
1707  // ...
1708}
1709
1710// 通过语句表示执行顺序,而非逗号运算符
1711let x = 0;
1712++x;
1713x = x++;
1714```
1715
1716### 不支持解构变量声明
1717
1718**规则:**`arkts-no-destruct-decls`
1719
1720**级别:错误**
1721
1722**错误码:10605074**
1723
1724ArkTS不支持解构变量声明。解构变量声明是一个依赖于结构兼容性的动态特性,且解构声明中的名称必须与被解构对象中的属性名称一致。
1725
1726**TypeScript**
1727
1728```typescript
1729class Point {
1730  x: number = 0.0
1731  y: number = 0.0
1732}
1733
1734function returnZeroPoint(): Point {
1735  return new Point();
1736}
1737
1738let {x, y} = returnZeroPoint();
1739```
1740
1741**ArkTS**
1742
1743```typescript
1744class Point {
1745  x: number = 0.0
1746  y: number = 0.0
1747}
1748
1749function returnZeroPoint(): Point {
1750  return new Point();
1751}
1752
1753// 创建一个局部变量来处理每个字段
1754let zp = returnZeroPoint();
1755let x = zp.x;
1756let y = zp.y;
1757```
1758
1759### 不支持在catch语句标注类型
1760
1761**规则:**`arkts-no-types-in-catch`
1762
1763**级别:错误**
1764
1765**错误码:10605079**
1766
1767TypeScript的catch语句中,只能标注`any`或`unknown`类型。ArkTS不支持这些类型,应省略类型标注。
1768
1769**TypeScript**
1770
1771```typescript
1772try {
1773  // ...
1774} catch (a: unknown) {
1775  // 处理异常
1776}
1777```
1778
1779**ArkTS**
1780
1781```typescript
1782try {
1783  // ...
1784} catch (a) {
1785  // 处理异常
1786}
1787```
1788
1789### 不支持`for .. in`
1790
1791**规则:**`arkts-no-for-in`
1792
1793**级别:错误**
1794
1795**错误码:10605080**
1796
1797由于在ArkTS中,对象布局在编译时是确定的并且在运行时无法修改,因此不支持使用`for .. in`迭代一个对象的属性。
1798
1799**TypeScript**
1800
1801```typescript
1802let a: string[] = ['1.0', '2.0', '3.0'];
1803for (let i in a) {
1804  console.log(a[i]);
1805}
1806```
1807
1808**ArkTS**
1809
1810```typescript
1811let a: string[] = ['1.0', '2.0', '3.0'];
1812for (let i = 0; i < a.length; ++i) {
1813  console.log(a[i]);
1814}
1815```
1816
1817### 不支持映射类型
1818
1819**规则:**`arkts-no-mapped-types`
1820
1821**级别:错误**
1822
1823**错误码:10605083**
1824
1825ArkTS不支持映射类型,使用其他语法来表示相同的语义。
1826
1827**TypeScript**
1828
1829```typescript
1830type OptionsFlags<Type> = {
1831  [Property in keyof Type]: boolean
1832}
1833```
1834
1835**ArkTS**
1836
1837```typescript
1838class C {
1839  n: number = 0
1840  s: string = ''
1841}
1842
1843class CFlags {
1844  n: boolean = false
1845  s: boolean = false
1846}
1847```
1848
1849### 不支持`with`语句
1850
1851**规则:**`arkts-no-with`
1852
1853**级别:错误**
1854
1855**错误码:10605084**
1856
1857ArkTS不支持`with`语句,使用其他语法来表示相同的语义。
1858
1859**TypeScript**
1860
1861```typescript
1862with (Math) { // 编译时错误, 但是仍能生成JavaScript代码
1863  let r: number = 42;
1864  let area: number = PI * r * r;
1865}
1866```
1867
1868**ArkTS**
1869
1870```typescript
1871let r: number = 42;
1872let area: number = Math.PI * r * r;
1873```
1874
1875### 限制`throw`语句中表达式的类型
1876
1877**规则:**`arkts-limited-throw`
1878
1879**级别:错误**
1880
1881**错误码:10605087**
1882
1883ArkTS只支持抛出`Error`类或其派生类的实例。禁止抛出其他类型的数据,例如`number`或`string`。
1884
1885**TypeScript**
1886
1887```typescript
1888throw 4;
1889throw '';
1890throw new Error();
1891```
1892
1893**ArkTS**
1894
1895```typescript
1896throw new Error();
1897```
1898
1899### 限制省略函数返回类型标注
1900
1901**规则:**`arkts-no-implicit-return-types`
1902
1903**级别:错误**
1904
1905**错误码:10605090**
1906
1907ArkTS在部分场景中支持对函数返回类型进行推断。当`return`语句中的表达式是对某个函数或方法进行调用,且该函数或方法的返回类型没有被显著标注时,会出现编译时错误。在这种情况下,请标注函数返回类型。
1908
1909**TypeScript**
1910
1911```typescript
1912// 只有在开启noImplicitAny选项时会产生编译时错误
1913function f(x: number) {
1914  if (x <= 0) {
1915    return x;
1916  }
1917  return g(x);
1918}
1919
1920// 只有在开启noImplicitAny选项时会产生编译时错误
1921function g(x: number) {
1922  return f(x - 1);
1923}
1924
1925function doOperation(x: number, y: number) {
1926  return x + y;
1927}
1928
1929f(10);
1930doOperation(2, 3);
1931```
1932
1933**ArkTS**
1934
1935```typescript
1936// 需标注返回类型:
1937function f(x: number): number {
1938  if (x <= 0) {
1939    return x;
1940  }
1941  return g(x);
1942}
1943
1944// 可以省略返回类型,返回类型可以从f的类型标注推导得到
1945function g(x: number): number {
1946  return f(x - 1);
1947}
1948
1949// 可以省略返回类型
1950function doOperation(x: number, y: number) {
1951  return x + y;
1952}
1953
1954f(10);
1955doOperation(2, 3);
1956```
1957
1958### 不支持参数解构的函数声明
1959
1960**规则:**`arkts-no-destruct-params`
1961
1962**级别:错误**
1963
1964**错误码:10605091**
1965
1966ArkTS要求实参必须直接传递给函数,且必须指定到形参。
1967
1968**TypeScript**
1969
1970```typescript
1971function drawText({ text = '', location: [x, y] = [0, 0], bold = false }) {
1972  text;
1973  x;
1974  y;
1975  bold;
1976}
1977
1978drawText({ text: 'Hello, world!', location: [100, 50], bold: true });
1979```
1980
1981**ArkTS**
1982
1983```typescript
1984function drawText(text: String, location: number[], bold: boolean) {
1985  let x = location[0];
1986  let y = location[1];
1987  text;
1988  x;
1989  y;
1990  bold;
1991}
1992
1993function main() {
1994  drawText('Hello, world!', [100, 50], true);
1995}
1996```
1997
1998### 不支持在函数内声明函数
1999
2000**规则:**`arkts-no-nested-funcs`
2001
2002**级别:错误**
2003
2004**错误码:10605092**
2005
2006ArkTS不支持在函数内声明函数,改用lambda函数。
2007
2008**TypeScript**
2009
2010```typescript
2011function addNum(a: number, b: number): void {
2012
2013  // 函数内声明函数
2014  function logToConsole(message: string): void {
2015    console.log(message);
2016  }
2017
2018  let result = a + b;
2019
2020  // 调用函数
2021  logToConsole('result is ' + result);
2022}
2023```
2024
2025**ArkTS**
2026
2027```typescript
2028function addNum(a: number, b: number): void {
2029  // 使用lambda函数代替声明函数
2030  let logToConsole: (message: string) => void = (message: string): void => {
2031    console.log(message);
2032  }
2033
2034  let result = a + b;
2035
2036  logToConsole('result is ' + result);
2037}
2038```
2039
2040### 不支持在函数和类的静态方法中使用`this`
2041
2042**规则:**`arkts-no-standalone-this`
2043
2044**级别:错误**
2045
2046**错误码:10605093**
2047
2048ArkTS中`this`只能在类的实例方法中使用,不支持在函数和类的静态方法中使用。
2049
2050**TypeScript**
2051
2052```typescript
2053function foo(i: string) {
2054  this.count = i; // 只有在开启noImplicitThis选项时会产生编译时错误
2055}
2056
2057class A {
2058  count: string = 'a'
2059  m = foo
2060}
2061
2062let a = new A();
2063console.log(a.count); // 打印a
2064a.m('b');
2065console.log(a.count); // 打印b
2066```
2067
2068**ArkTS**
2069
2070```typescript
2071class A {
2072  count: string = 'a'
2073  m(i: string): void {
2074    this.count = i;
2075  }
2076}
2077
2078function main(): void {
2079  let a = new A();
2080  console.log(a.count);  // 打印a
2081  a.m('b');
2082  console.log(a.count);  // 打印b
2083}
2084```
2085
2086### 不支持生成器函数
2087
2088**规则:**`arkts-no-generators`
2089
2090**级别:错误**
2091
2092**错误码:10605094**
2093
2094目前ArkTS不支持生成器函数,可使用`async`或`await`机制处理并行任务。
2095
2096**TypeScript**
2097
2098```typescript
2099function* counter(start: number, end: number) {
2100  for (let i = start; i <= end; i++) {
2101    yield i;
2102  }
2103}
2104
2105for (let num of counter(1, 5)) {
2106  console.log(num);
2107}
2108```
2109
2110**ArkTS**
2111
2112```typescript
2113async function complexNumberProcessing(num: number): Promise<number> {
2114  // ...
2115  return num;
2116}
2117
2118async function foo() {
2119  for (let i = 1; i <= 5; i++) {
2120    await complexNumberProcessing(i);
2121  }
2122}
2123
2124foo()
2125```
2126
2127### 使用`instanceof`和`as`进行类型保护
2128
2129**规则:**`arkts-no-is`
2130
2131**级别:错误**
2132
2133**错误码:10605096**
2134
2135ArkTS不支持`is`运算符,必须用`instanceof`运算符替代。在使用之前,必须使用`as`运算符将对象转换为需要的类型。
2136
2137**TypeScript**
2138
2139```typescript
2140class Foo {
2141  foo: string = ''
2142  common: string = ''
2143}
2144
2145class Bar {
2146  bar: string = ''
2147  common: string = ''
2148}
2149
2150function isFoo(arg: any): arg is Foo {
2151  return arg.foo !== undefined;
2152}
2153
2154function doStuff(arg: Foo | Bar) {
2155  if (isFoo(arg)) {
2156    console.log(arg.foo);  // OK
2157    console.log(arg.bar);  // 编译时错误
2158  } else {
2159    console.log(arg.foo);  // 编译时错误
2160    console.log(arg.bar);  // OK
2161  }
2162}
2163
2164doStuff({ foo: 123, common: '123' });
2165doStuff({ bar: 123, common: '123' });
2166```
2167
2168**ArkTS**
2169
2170```typescript
2171class Foo {
2172  foo: string = ''
2173  common: string = ''
2174}
2175
2176class Bar {
2177  bar: string = ''
2178  common: string = ''
2179}
2180
2181function isFoo(arg: Object): boolean {
2182  return arg instanceof Foo;
2183}
2184
2185function doStuff(arg: Object): void {
2186  if (isFoo(arg)) {
2187    let fooArg = arg as Foo;
2188    console.log(fooArg.foo);   // OK
2189    console.log(arg.bar);    // 编译时错误
2190  } else {
2191    let barArg = arg as Bar;
2192    console.log(arg.foo);    // 编译时错误
2193    console.log(barArg.bar);   // OK
2194  }
2195}
2196
2197function main(): void {
2198  doStuff(new Foo());
2199  doStuff(new Bar());
2200}
2201```
2202
2203### 部分支持展开运算符
2204
2205**规则:**`arkts-no-spread`
2206
2207**级别:错误**
2208
2209**错误码:10605099**
2210
2211ArkTS仅支持使用展开运算符展开数组、`Array`的子类和`TypedArray`(例如`Int32Array`)。仅支持使用在以下场景中:
22121. 传递给剩余参数时;
22132. 复制一个数组到数组字面量。
2214
2215**TypeScript**
2216
2217```typescript
2218function foo(x: number, y: number, z: number) {
2219  // ...
2220}
2221
2222let args: [number, number, number] = [0, 1, 2];
2223foo(...args);
2224```
2225
2226**ArkTS**
2227
2228```typescript
2229function log_numbers(x: number, y: number, z: number) {
2230  // ...
2231}
2232
2233let numbers: number[] = [1, 2, 3];
2234log_numbers(numbers[0], numbers[1], numbers[2]);
2235```
2236
2237**TypeScript**
2238
2239```typescript
2240let point2d = { x: 1, y: 2 };
2241let point3d = { ...point2d, z: 3 };
2242```
2243
2244**ArkTS**
2245
2246```typescript
2247class Point2D {
2248  x: number = 0; y: number = 0
2249}
2250
2251class Point3D {
2252  x: number = 0; y: number = 0; z: number = 0
2253  constructor(p2d: Point2D, z: number) {
2254    this.x = p2d.x;
2255    this.y = p2d.y;
2256    this.z = z;
2257  }
2258}
2259
2260let p3d = new Point3D({ x: 1, y: 2 } as Point2D, 3);
2261
2262class DerivedFromArray extends Uint16Array {};
2263
2264let arr1 = [1, 2, 3];
2265let arr2 = new Uint16Array([4, 5, 6]);
2266let arr3 = new DerivedFromArray([7, 8, 9]);
2267let arr4 = [...arr1, 10, ...arr2, 11, ...arr3];
2268```
2269
2270### 接口不能继承具有相同方法的两个接口
2271
2272**规则:**`arkts-no-extend-same-prop`
2273
2274**级别:错误**
2275
2276**错误码:106050102**
2277
2278在TypeScript中,如果一个接口继承了两个具有相同方法的接口,则必须使用联合类型声明该方法的返回值类型。在ArkTS中,由于接口不能包含两个无法区分的方法(如参数列表相同但返回类型不同),因此不能继承具有相同方法的两个接口。
2279
2280**TypeScript**
2281
2282```typescript
2283interface Mover {
2284  getStatus(): { speed: number }
2285}
2286interface Shaker {
2287  getStatus(): { frequency: number }
2288}
2289
2290interface MoverShaker extends Mover, Shaker {
2291  getStatus(): {
2292    speed: number
2293    frequency: number
2294  }
2295}
2296
2297class C implements MoverShaker {
2298  private speed: number = 0
2299  private frequency: number = 0
2300
2301  getStatus() {
2302    return { speed: this.speed, frequency: this.frequency };
2303  }
2304}
2305```
2306
2307**ArkTS**
2308
2309```typescript
2310class MoveStatus {
2311  public speed: number
2312  constructor() {
2313    this.speed = 0;
2314  }
2315}
2316interface Mover {
2317  getMoveStatus(): MoveStatus
2318}
2319
2320class ShakeStatus {
2321  public frequency: number
2322  constructor() {
2323    this.frequency = 0;
2324  }
2325}
2326interface Shaker {
2327  getShakeStatus(): ShakeStatus
2328}
2329
2330class MoveAndShakeStatus {
2331  public speed: number
2332  public frequency: number
2333  constructor() {
2334    this.speed = 0;
2335    this.frequency = 0;
2336  }
2337}
2338
2339class C implements Mover, Shaker {
2340  private move_status: MoveStatus
2341  private shake_status: ShakeStatus
2342
2343  constructor() {
2344    this.move_status = new MoveStatus();
2345    this.shake_status = new ShakeStatus();
2346  }
2347
2348  public getMoveStatus(): MoveStatus {
2349    return this.move_status;
2350  }
2351
2352  public getShakeStatus(): ShakeStatus {
2353    return this.shake_status;
2354  }
2355
2356  public getStatus(): MoveAndShakeStatus {
2357    return {
2358      speed: this.move_status.speed,
2359      frequency: this.shake_status.frequency
2360    };
2361  }
2362}
2363```
2364
2365### 不支持声明合并
2366
2367**规则:**`arkts-no-decl-merging`
2368
2369**级别:错误**
2370
2371**错误码:10605103**
2372
2373ArkTS不支持类和接口的声明合并。
2374
2375**TypeScript**
2376
2377```typescript
2378interface Document {
2379  createElement(tagName: any): Element
2380}
2381
2382interface Document {
2383  createElement(tagName: string): HTMLElement
2384}
2385
2386interface Document {
2387  createElement(tagName: number): HTMLDivElement
2388  createElement(tagName: boolean): HTMLSpanElement
2389  createElement(tagName: string, value: number): HTMLCanvasElement
2390}
2391```
2392
2393**ArkTS**
2394
2395```typescript
2396interface Document {
2397  createElement(tagName: number): HTMLDivElement
2398  createElement(tagName: boolean): HTMLSpanElement
2399  createElement(tagName: string, value: number): HTMLCanvasElement
2400  createElement(tagName: string): HTMLElement
2401  createElement(tagName: Object): Element
2402}
2403```
2404
2405### 接口不能继承类
2406
2407**规则:**`arkts-extends-only-class`
2408
2409**级别:错误**
2410
2411**错误码:10605104**
2412
2413ArkTS中,接口不能继承类,只能继承其他接口。
2414
2415**TypeScript**
2416
2417```typescript
2418class Control {
2419  state: number = 0
2420}
2421
2422interface SelectableControl extends Control {
2423  select(): void
2424}
2425```
2426
2427**ArkTS**
2428
2429```typescript
2430interface Control {
2431  state: number
2432}
2433
2434interface SelectableControl extends Control {
2435  select(): void
2436}
2437```
2438
2439### 不支持构造函数类型
2440
2441**规则:**`arkts-no-ctor-signatures-funcs`
2442
2443**级别:错误**
2444
2445**错误码:10605106**
2446
2447ArkTS不支持构造函数类型,改用lambda函数。
2448
2449**TypeScript**
2450
2451```typescript
2452class Person {
2453  constructor(
2454    name: string,
2455    age: number
2456  ) {}
2457}
2458type PersonCtor = new (name: string, age: number) => Person
2459
2460function createPerson(Ctor: PersonCtor, name: string, age: number): Person
2461{
2462  return new Ctor(name, age);
2463}
2464
2465const person = createPerson(Person, 'John', 30);
2466```
2467
2468**ArkTS**
2469
2470```typescript
2471class Person {
2472  constructor(
2473    name: string,
2474    age: number
2475  ) {}
2476}
2477type PersonCtor = (n: string, a: number) => Person
2478
2479function createPerson(Ctor: PersonCtor, n: string, a: number): Person {
2480  return Ctor(n, a);
2481}
2482
2483let Impersonizer: PersonCtor = (n: string, a: number): Person => {
2484  return new Person(n, a);
2485}
2486
2487const person = createPerson(Impersonizer, 'John', 30);
2488```
2489
2490### 只能使用类型相同的编译时表达式初始化枚举成员
2491
2492**规则:**`arkts-no-enum-mixed-types`
2493
2494**级别:错误**
2495
2496**错误码:10605111**
2497
2498ArkTS不支持使用运行期间计算的表达式初始化枚举成员。枚举中所有显式初始化的成员必须具有相同类型。
2499
2500**TypeScript**
2501
2502```typescript
2503enum E1 {
2504  A = 0xa,
2505  B = 0xb,
2506  C = Math.random(),
2507  D = 0xd,
2508  E // 推断出0xe
2509}
2510
2511enum E2 {
2512  A = 0xa,
2513  B = '0xb',
2514  C = 0xc,
2515  D = '0xd'
2516}
2517```
2518
2519**ArkTS**
2520
2521```typescript
2522enum E1 {
2523  A = 0xa,
2524  B = 0xb,
2525  C = 0xc,
2526  D = 0xd,
2527  E // 推断出0xe
2528}
2529
2530enum E2 {
2531  A = '0xa',
2532  B = '0xb',
2533  C = '0xc',
2534  D = '0xd'
2535}
2536```
2537
2538### 不支持`enum`声明合并
2539
2540**规则:**`arkts-no-enum-merging`
2541
2542**级别:错误**
2543
2544**错误码:10605113**
2545
2546ArkTS不支持`enum`声明合并。
2547
2548**TypeScript**
2549
2550```typescript
2551enum ColorSet {
2552  RED,
2553  GREEN
2554}
2555enum ColorSet {
2556  YELLOW = 2
2557}
2558enum ColorSet {
2559  BLACK = 3,
2560  BLUE
2561}
2562```
2563
2564**ArkTS**
2565
2566```typescript
2567enum ColorSet {
2568  RED,
2569  GREEN,
2570  YELLOW,
2571  BLACK,
2572  BLUE
2573}
2574```
2575
2576### 命名空间不能被用作对象
2577
2578**规则:**`arkts-no-ns-as-obj`
2579
2580**级别:错误**
2581
2582**错误码:10605114**
2583
2584ArkTS不支持将命名空间用作对象,可以使用类或模块。
2585
2586**TypeScript**
2587
2588```typescript
2589namespace MyNamespace {
2590  export let x: number
2591}
2592
2593let m = MyNamespace;
2594m.x = 2;
2595```
2596
2597**ArkTS**
2598
2599```typescript
2600namespace MyNamespace {
2601  export let x: number
2602}
2603
2604MyNamespace.x = 2;
2605```
2606
2607### 不支持命名空间中的非声明语句
2608
2609**规则:**`arkts-no-ns-statements`
2610
2611**级别:错误**
2612
2613**错误码:10605116**
2614
2615在ArkTS中,命名空间用于定义标识符的可见范围,仅在编译时有效。因此,命名空间中不支持非声明语句。可以将非声明语句写在函数中。
2616
2617**TypeScript**
2618
2619```typescript
2620namespace A {
2621  export let x: number
2622  x = 1;
2623}
2624```
2625
2626**ArkTS**
2627
2628```typescript
2629namespace A {
2630  export let x: number
2631
2632  export function init() {
2633    x = 1;
2634  }
2635}
2636
2637// 调用初始化函数来执行
2638A.init();
2639```
2640
2641### 不支持`require`和`import`赋值表达式
2642
2643**规则:**`arkts-no-require`
2644
2645**级别:错误**
2646
2647**错误码:10605121**
2648
2649ArkTS不支持通过`require`导入和`import`赋值表达式,改用`import`。
2650
2651**TypeScript**
2652
2653```typescript
2654import m = require('mod')
2655```
2656
2657**ArkTS**
2658
2659```typescript
2660import * as m from 'mod'
2661```
2662
2663### 不支持`export = ...`语法
2664
2665**规则:**`arkts-no-export-assignment`
2666
2667**级别:错误**
2668
2669**错误码:10605126**
2670
2671ArkTS不支持`export = ...`语法,改用常规的`export`或`import`。
2672
2673**TypeScript**
2674
2675```typescript
2676// module1
2677export = Point
2678
2679class Point {
2680  constructor(x: number, y: number) {}
2681  static origin = new Point(0, 0)
2682}
2683
2684// module2
2685import Pt = require('module1')
2686
2687let p = Pt.Point.origin;
2688```
2689
2690**ArkTS**
2691
2692```typescript
2693// module1
2694export class Point {
2695  constructor(x: number, y: number) {}
2696  static origin = new Point(0, 0)
2697}
2698
2699// module2
2700import * as Pt from 'module1'
2701
2702let p = Pt.Point.origin
2703```
2704
2705### 不支持ambient module声明
2706
2707**规则:**`arkts-no-ambient-decls`
2708
2709**级别:错误**
2710
2711**错误码:10605128**
2712
2713由于ArkTS本身有与JavaScript交互的机制,ArkTS不支持ambient module声明。
2714
2715**TypeScript**
2716
2717```typescript
2718declare module 'someModule' {
2719  export function normalize(s: string): string;
2720}
2721```
2722
2723**ArkTS**
2724
2725```typescript
2726// 从原始模块中导入需要的内容
2727import { normalize } from 'someModule'
2728```
2729
2730### 不支持在模块名中使用通配符
2731
2732**规则:**`arkts-no-module-wildcards`
2733
2734**级别:错误**
2735
2736**错误码:10605129**
2737
2738在ArkTS中,导入是编译时而非运行时行为,不支持在模块名中使用通配符。
2739
2740**TypeScript**
2741
2742```typescript
2743// 声明
2744declare module '*!text' {
2745  const content: string
2746  export default content
2747}
2748
2749// 使用代码
2750import fileContent from 'some.txt!text'
2751```
2752
2753**ArkTS**
2754
2755```typescript
2756// 声明
2757declare namespace N {
2758  function foo(x: number): number
2759}
2760
2761// 使用代码
2762import * as m from 'module'
2763console.log('N.foo called: ' + N.foo(42));
2764```
2765
2766### 不支持通用模块定义(UMD)
2767
2768**规则:**`arkts-no-umd`
2769
2770**级别:错误**
2771
2772**错误码:10605130**
2773
2774ArkTS不支持通用模块定义(UMD)。因为在ArkTS中没有“脚本”的概念(相对于“模块”)。此外,在ArkTS中,导入是编译时而非运行时特性。改用`export`和`import`语法。
2775
2776**TypeScript**
2777
2778```typescript
2779// math-lib.d.ts
2780export const isPrime(x: number): boolean
2781export as namespace mathLib
2782
2783// 脚本中
2784mathLib.isPrime(2)
2785```
2786
2787**ArkTS**
2788
2789```typescript
2790// math-lib.d.ts
2791namespace mathLib {
2792  export isPrime(x: number): boolean
2793}
2794
2795// 程序中
2796import { mathLib } from 'math-lib'
2797mathLib.isPrime(2)
2798```
2799
2800### 不支持`new.target`
2801
2802**规则:**`arkts-no-new-target`
2803
2804**级别:错误**
2805
2806**错误码:10605132**
2807
2808ArkTS没有原型的概念,因此不支持`new.target`。此特性不符合静态类型的原则。
2809
2810### 不支持确定赋值断言
2811
2812**规则:**`arkts-no-definite-assignment`
2813
2814**级别:警告**
2815
2816**错误码:10605134**
2817
2818ArkTS不支持确定赋值断言,例如:`let v!: T`。改为在声明变量的同时为变量赋值。
2819
2820**TypeScript**
2821
2822```typescript
2823let x!: number // 提示:在使用前将x初始化
2824
2825initialize();
2826
2827function initialize() {
2828  x = 10;
2829}
2830
2831console.log('x = ' + x);
2832```
2833
2834**ArkTS**
2835
2836```typescript
2837function initialize(): number {
2838  return 10;
2839}
2840
2841let x: number = initialize();
2842
2843console.log('x = ' + x);
2844```
2845
2846### 不支持在原型上赋值
2847
2848**规则:**`arkts-no-prototype-assignment`
2849
2850**级别:错误**
2851
2852**错误码:10605136**
2853
2854ArkTS没有原型的概念,因此不支持在原型上赋值。此特性不符合静态类型的原则。
2855
2856**TypeScript**
2857
2858```typescript
2859let C = function(p) {
2860  this.p = p; // 只有在开启noImplicitThis选项时会产生编译时错误
2861}
2862
2863C.prototype = {
2864  m() {
2865    console.log(this.p);
2866  }
2867}
2868
2869C.prototype.q = function(r: string) {
2870  return this.p == r;
2871}
2872```
2873
2874**ArkTS**
2875
2876```typescript
2877class C {
2878  p: string = ''
2879  m() {
2880    console.log(this.p);
2881  }
2882  q(r: string) {
2883    return this.p == r;
2884  }
2885}
2886```
2887
2888### 不支持`globalThis`
2889
2890**规则:**`arkts-no-globalthis`
2891
2892**级别:警告**
2893
2894**错误码:10605137**
2895
2896由于ArkTS不支持动态更改对象的布局,因此不支持全局作用域和`globalThis`。
2897
2898**TypeScript**
2899
2900```typescript
2901// 全局文件中
2902var abc = 100;
2903
2904// 从上面引用'abc'
2905let x = globalThis.abc;
2906```
2907
2908**ArkTS**
2909
2910```typescript
2911// file1
2912export let abc: number = 100;
2913
2914// file2
2915import * as M from 'file1'
2916
2917let x = M.abc;
2918```
2919
2920### 不支持一些utility类型
2921
2922**规则:**`arkts-no-utility-types`
2923
2924**级别:错误**
2925
2926**错误码:10605138**
2927
2928ArkTS仅支持`Partial`、`Required`、`Readonly`和`Record`,不支持TypeScript中其他的`Utility Types`。
2929
2930对于`Partial<T>`类型,泛型参数T必须为类或者接口类型。
2931
2932对于`Record`类型的对象,通过索引访问到的值的类型是包含`undefined`的联合类型。
2933
2934### 不支持对函数声明属性
2935
2936**规则:**`arkts-no-func-props`
2937
2938**级别:错误**
2939
2940**错误码:10605139**
2941
2942由于ArkTS不支持动态改变函数对象布局,因此,不支持对函数声明属性。
2943
2944### 不支持`Function.apply`和`Function.call`
2945
2946**规则:**`arkts-no-func-apply-call`
2947
2948**级别:错误**
2949
2950**错误码:10605152**
2951
2952ArkTS不允许使用标准库函数`Function.apply`和`Function.call`。这些函数用于显式设置被调用函数的`this`参数。在ArkTS中,`this`的语义仅限于传统的OOP风格,函数体中禁止使用`this`。
2953
2954### 不支持`Function.bind`
2955
2956**规则:**`arkts-no-func-bind`
2957
2958**级别:警告**
2959
2960**错误码:10605140**
2961
2962ArkTS禁用标准库函数`Function.bind`。标准库使用这些函数显式设置被调用函数的`this`参数。在ArkTS中,`this`仅限于传统OOP风格,函数体中禁用使用`this`。
2963
2964
2965### 不支持`as const`断言
2966
2967**规则:**`arkts-no-as-const`
2968
2969**级别:错误**
2970
2971**错误码:10605142**
2972
2973ArkTS不支持`as const`断言和字面量类型。标准TypeScript中,`as const`用于标注字面量类型。
2974
2975**TypeScript**
2976
2977```typescript
2978// 'hello'类型
2979let x = 'hello' as const;
2980
2981// 'readonly [10, 20]'类型
2982let y = [10, 20] as const;
2983
2984// '{ readonly text: 'hello' }'类型
2985let z = { text: 'hello' } as const;
2986```
2987
2988**ArkTS**
2989
2990```typescript
2991// 'string'类型
2992let x: string = 'hello';
2993
2994// 'number[]'类型
2995let y: number[] = [10, 20];
2996
2997class Label {
2998  text: string = ''
2999}
3000
3001// 'Label'类型
3002let z: Label = {
3003  text: 'hello'
3004}
3005```
3006
3007### 不支持导入断言
3008
3009**规则:**`arkts-no-import-assertions`
3010
3011**级别:错误**
3012
3013**错误码:10605143**
3014
3015ArkTS不支持导入断言。因为导入是编译时特性,运行时检查导入API是否正确没有意义。改用常规的`import`语法。
3016
3017**TypeScript**
3018
3019```typescript
3020import { obj } from 'something.json' assert { type: 'json' }
3021```
3022
3023**ArkTS**
3024
3025```typescript
3026// 编译时将检查导入T的正确性
3027import { something } from 'module'
3028```
3029
3030### 限制使用标准库
3031
3032**规则:**`arkts-limited-stdlib`
3033
3034**级别:错误**
3035
3036**错误码:10605144**
3037
3038ArkTS不允许使用TypeScript或JavaScript标准库中的某些接口。大部分接口与动态特性有关。ArkTS中禁止使用以下接口:
3039
3040全局对象的属性和方法:`eval`
3041
3042`Object`:`__proto__`、`__defineGetter__`、`__defineSetter__`、
3043`__lookupGetter__`、`__lookupSetter__`、`assign`、`create`、
3044`defineProperties`、`defineProperty`、`freeze`、
3045`fromEntries`、`getOwnPropertyDescriptor`、`getOwnPropertyDescriptors`、
3046`getOwnPropertySymbols`、`getPrototypeOf`、
3047`hasOwnProperty`、`is`、`isExtensible`、`isFrozen`、
3048`isPrototypeOf`、`isSealed`、`preventExtensions`、
3049`propertyIsEnumerable`、`seal`、`setPrototypeOf`
3050
3051`Reflect`:`apply`、`construct`、`defineProperty`、`deleteProperty`、
3052`getOwnPropertyDescriptor`、`getPrototypeOf`、
3053`isExtensible`、`preventExtensions`、
3054`setPrototypeOf`
3055
3056`Proxy`:`handler.apply()`、`handler.construct()`、
3057`handler.defineProperty()`、`handler.deleteProperty()`、`handler.get()`、
3058`handler.getOwnPropertyDescriptor()`、`handler.getPrototypeOf()`、
3059`handler.has()`、`handler.isExtensible()`、`handler.ownKeys()`、
3060`handler.preventExtensions()`、`handler.set()`、`handler.setPrototypeOf()`
3061
3062### 强制进行严格类型检查
3063
3064**规则:**`arkts-strict-typing`
3065
3066**级别:错误**
3067
3068**错误码:10605145**
3069
3070在编译阶段,会进行TypeScript严格模式的类型检查,包括:
3071`noImplicitReturns`,
3072`strictFunctionTypes`,
3073`strictNullChecks`,
3074`strictPropertyInitialization`。
3075
3076**TypeScript**
3077
3078```typescript
3079// 只有在开启noImplicitReturns选项时会产生编译时错误
3080function foo(s: string): string {
3081  if (s != '') {
3082    console.log(s);
3083    return s;
3084  } else {
3085    console.log(s);
3086  }
3087}
3088
3089let n: number = null; // 只有在开启strictNullChecks选项时会产生编译时错误
3090```
3091
3092**ArkTS**
3093
3094```typescript
3095function foo(s: string): string {
3096  console.log(s);
3097  return s;
3098}
3099
3100let n1: number | null = null;
3101let n2: number = 0;
3102```
3103
3104在定义类时,如果无法在声明时或者构造函数中初始化某实例属性,那么可以使用确定赋值断言符`!`来消除`strictPropertyInitialization`的报错。
3105
3106使用确定赋值断言符会增加代码错误风险。开发者需确保实例属性在使用前已赋值,否则可能产生运行时异常。
3107
3108使用确定赋值断言符会增加运行时开销,应尽量避免使用。
3109
3110使用确定赋值断言符将产生`warning: arkts-no-definite-assignment`。
3111
3112**TypeScript**
3113
3114```typescript
3115class C {
3116  name: string  // 只有在开启strictPropertyInitialization选项时会产生编译时错误
3117  age: number   // 只有在开启strictPropertyInitialization选项时会产生编译时错误
3118}
3119
3120let c = new C();
3121```
3122
3123**ArkTS**
3124
3125```typescript
3126class C {
3127  name: string = ''
3128  age!: number      // warning: arkts-no-definite-assignment
3129
3130  initAge(age: number) {
3131    this.age = age;
3132  }
3133}
3134
3135let c = new C();
3136c.initAge(10);
3137```
3138
3139### 不允许通过注释关闭类型检查
3140
3141**规则:**`arkts-strict-typing-required`
3142
3143**级别:错误**
3144
3145**错误码:10605146**
3146
3147在ArkTS中,类型检查不是可选项。不允许通过注释关闭类型检查,不支持使用`@ts-ignore`和`@ts-nocheck`。
3148
3149**TypeScript**
3150
3151```typescript
3152// @ts-nocheck
3153// ...
3154// 关闭了类型检查后的代码
3155// ...
3156
3157let s1: string = null; // 没有报错
3158
3159// @ts-ignore
3160let s2: string = null; // 没有报错
3161```
3162
3163**ArkTS**
3164
3165```typescript
3166let s1: string | null = null; // 没有报错,合适的类型
3167let s2: string = null; // 编译时报错
3168```
3169
3170### 允许.ets文件`import`.ets/.ts/.js文件源码, 不允许.ts/.js文件`import`.ets文件源码
3171
3172**规则:**`arkts-no-ts-deps`
3173
3174**级别:错误**
3175
3176**错误码:10605147**
3177
3178.ets文件可以`import`.ets/.ts/.js文件源码,但是.ts/.js文件不允许`import`.ets文件源码。
3179
3180**TypeScript**
3181
3182```typescript
3183// app.ets
3184export class C {
3185  // ...
3186}
3187
3188// lib.ts
3189import { C } from 'app'
3190```
3191
3192**ArkTS**
3193
3194```typescript
3195// lib1.ets
3196export class C {
3197  // ...
3198}
3199
3200// lib2.ets
3201import { C } from 'lib1'
3202```
3203
3204### `class`不能被用作对象
3205
3206**规则:**`arkts-no-classes-as-obj`
3207
3208**级别:警告**
3209
3210**错误码:10605149**
3211
3212在ArkTS中,`class`声明的是一个新类型,不是值。因此,不支持将`class`用作对象,例如将其赋值给一个对象。
3213
3214### 不支持在`import`语句前使用其他语句
3215
3216**规则:**`arkts-no-misplaced-imports`
3217
3218**级别:错误**
3219
3220**错误码:10605150**
3221
3222在ArkTS中,除动态`import`语句外,所有`import`语句需置于其他语句之前。
3223
3224**TypeScript**
3225
3226```typescript
3227class C {
3228  s: string = ''
3229  n: number = 0
3230}
3231
3232import foo from 'module1'
3233```
3234
3235**ArkTS**
3236
3237```typescript
3238import foo from 'module1'
3239
3240class C {
3241  s: string = ''
3242  n: number = 0
3243}
3244
3245import('module2').then(() => {}).catch(() => {})  // 动态import
3246```
3247
3248### 限制使用`ESObject`类型
3249
3250**规则:**`arkts-limited-esobj`
3251
3252**级别:警告**
3253
3254**错误码:10605151**
3255
3256为了防止动态对象(来自.ts/.js文件)在静态代码(.ets文件)中的滥用,`ESObject`类型在ArkTS中的使用是受限的。
3257在API版本18以前,唯一允许使用`ESObject`类型的场景是局部变量的声明。`ESObject`类型变量只能被跨语言调用的对象赋值,例如:`ESObject`、`any`、`unknown`、匿名类型等。禁止使用在.ets文件中定义的静态类型值初始化`ESObject`类型变量。`ESObject`类型变量只能用于跨语言调用的函数或赋值给另一个`ESObject`类型变量。
3258
3259**ArkTS**
3260
3261```typescript
3262// lib.d.ts
3263declare function foo(): any;
3264declare function bar(a: any): number;
3265
3266// main.ets
3267let e0: ESObject = foo(); // 编译时错误:ESObject类型只能用于局部变量
3268
3269function f() {
3270  let e1 = foo();        // 编译时错误:e1的类型是any
3271  let e2: ESObject = 1;  // 编译时错误:不能用非动态值初始化ESObject类型变量
3272  let e3: ESObject = {}; // 编译时错误:不能用非动态值初始化ESObject类型变量
3273  let e4: ESObject = []; // 编译时错误:不能用非动态值初始化ESObject类型变量
3274  let e5: ESObject = ''; // 编译时错误:不能用非动态值初始化ESObject类型变量
3275  e5['prop'];            // 编译时错误:不能访问ESObject类型变量的属性
3276  e5[1];                 // 编译时错误:不能访问ESObject类型变量的属性
3277  e5.prop;               // 编译时错误:不能访问ESObject类型变量的属性
3278
3279  let e6: ESObject = foo(); // OK,显式标注ESObject类型
3280  let e7 = e6;              // OK,使用ESObject类型赋值
3281  bar(e7);                  // OK,ESObject类型变量传给跨语言调用的函数
3282}
3283```
3284