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