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