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